diff --git a/client/python/cli/command/__init__.py b/client/python/cli/command/__init__.py
index 53216f3162..ea48547f87 100644
--- a/client/python/cli/command/__init__.py
+++ b/client/python/cli/command/__init__.py
@@ -186,7 +186,5 @@ def validate(self) -> None:
"""
Used to validate a command. Should always be called before `execute`. The arg parser will catch many issues
with options, but this is used to apply additional constraints that the arg parser can't currently handle.
- One example is that a catalog cannot be created with the `s3` storage type without a `--role-arn` option, but
- one can be created without this flag if it's using the `gcs` storage type.
"""
raise Exception("`validate` called on abstract `Command`")
diff --git a/client/python/cli/constants.py b/client/python/cli/constants.py
index 82a4f5d01e..7892ff89cb 100644
--- a/client/python/cli/constants.py
+++ b/client/python/cli/constants.py
@@ -224,7 +224,7 @@ class Create:
"Multiple locations can be provided by specifying this option more than once."
)
- ROLE_ARN = "(Only for S3) A role ARN to use when connecting to S3"
+ ROLE_ARN = "(Only for AWS S3) A role ARN to use when connecting to S3"
EXTERNAL_ID = "(Only for S3) The external ID to use when connecting to S3"
REGION = "(Only for S3) The region to use when connecting to S3"
USER_ARN = "(Only for S3) A user ARN to use when connecting to S3"
diff --git a/site/content/_index.adoc b/site/content/_index.adoc
index 8cdbfd7da6..b493f07315 100644
--- a/site/content/_index.adoc
+++ b/site/content/_index.adoc
@@ -25,7 +25,7 @@ cascade:
{{< blocks/cover title="Welcome to the Apache Polaris™ (incubating) web site!" image_anchor="center" color="primary" >}}
Apache Polaris is an open-source, fully-featured catalog for Apache Iceberg™. It implements Iceberg's REST API, enabling seamless multi-engine interoperability across a wide range of platforms, including Apache Doris™, Apache Flink®, Apache Spark™, Dremio® OSS, StarRocks, and Trino.
-Get Started
+Get Started
{{< /blocks/cover >}}
diff --git a/site/content/in-dev/unreleased/command-line-interface.md b/site/content/in-dev/unreleased/command-line-interface.md
index 5f7ab65bde..acfe5aceab 100644
--- a/site/content/in-dev/unreleased/command-line-interface.md
+++ b/site/content/in-dev/unreleased/command-line-interface.md
@@ -133,8 +133,12 @@ options:
--type The type of catalog to create in [INTERNAL, EXTERNAL]. INTERNAL by default.
--storage-type (Required) The type of storage to use for the catalog
--default-base-location (Required) Default base location of the catalog
+ --endpoint (Only for S3) The S3 endpoint to use when connecting to S3
+ --endpoint-internal (Only for S3) The S3 endpoint used by Polaris to use when connecting to S3, if different from the one that clients use
+ --sts-endpoint (Only for S3) The STS endpoint to use when connecting to STS
+ --path-style-access (Only for S3) Whether to use path-style-access for S3
--allowed-location An allowed location for files tracked by the catalog. Multiple locations can be provided by specifying this option more than once.
- --role-arn (Required for S3) A role ARN to use when connecting to S3
+ --role-arn (Only for AWS S3) A role ARN to use when connecting to S3
--region (Only for S3) The region to use when connecting to S3
--external-id (Only for S3) The external ID to use when connecting to S3
--tenant-id (Required for Azure) A tenant ID to use when connecting to Azure Storage
@@ -145,7 +149,7 @@ options:
--catalog-connection-type The type of external catalog in [ICEBERG, HADOOP].
--iceberg-remote-catalog-name The remote catalog name when federating to an Iceberg REST catalog
--hadoop-warehouse The warehouse to use when federating to a HADOOP catalog
- --catalog-authentication-type The type of authentication in [OAUTH, BEARER, SIGV4]
+ --catalog-authentication-type The type of authentication in [OAUTH, BEARER, SIGV4, IMPLICIT]
--catalog-service-identity-type The type of service identity in [AWS_IAM]
--catalog-service-identity-iam-arn When using the AWS_IAM service identity type, this is the ARN of the IAM user or IAM role Polaris uses to assume roles and then access external resources.
--catalog-uri The URI of the external catalog
diff --git a/site/content/in-dev/unreleased/getting-started/creating-a-catalog/s3/_index.md b/site/content/in-dev/unreleased/getting-started/creating-a-catalog/s3/_index.md
index 2bf78106f8..538bca17a9 100644
--- a/site/content/in-dev/unreleased/getting-started/creating-a-catalog/s3/_index.md
+++ b/site/content/in-dev/unreleased/getting-started/creating-a-catalog/s3/_index.md
@@ -32,7 +32,7 @@ For the `polaris catalogs create` [command]({{% ref "../../../command-line-inter
```text
--storage-type s3
---role-arn (Required for S3) A role ARN to use when connecting to S3
+--role-arn (Only for AWS S3) A role ARN to use when connecting to S3
--region (Only for S3) The region to use when connecting to S3
--external-id (Only for S3) The external ID to use when connecting to S3
```
diff --git a/site/content/in-dev/unreleased/getting-started/using-polaris.md b/site/content/in-dev/unreleased/getting-started/using-polaris/_index.md
similarity index 89%
rename from site/content/in-dev/unreleased/getting-started/using-polaris.md
rename to site/content/in-dev/unreleased/getting-started/using-polaris/_index.md
index 981c9fc356..a2e9f521a5 100644
--- a/site/content/in-dev/unreleased/getting-started/using-polaris.md
+++ b/site/content/in-dev/unreleased/getting-started/using-polaris/_index.md
@@ -19,7 +19,7 @@
#
Title: Using Polaris
type: docs
-weight: 400
+weight: 401
---
## Setup
@@ -34,17 +34,17 @@ export CLIENT_SECRET=YOUR_CLIENT_SECRET
Refer to the [Creating a Catalog]({{% ref "creating-a-catalog" %}}) page for instructions on defining a
catalog for your specific storage type. The following examples assume the catalog's name is `quickstart_catalog`.
-In Polaris, the [catalog]({{% relref "../entities#catalog" %}}) is the top-level entity that objects like [tables]({{% relref "../entities#table" %}}) and [views]({{% relref "../entities#view" %}}) are organized under.
+In Polaris, the [catalog]({{% relref "../../entities#catalog" %}}) is the top-level entity that objects like [tables]({{% relref "../../entities#table" %}}) and [views]({{% relref "../../entities#view" %}}) are organized under.
The `DEFAULT_BASE_LOCATION` value you provided at catalog creation time will be the default location that objects in
this catalog should be stored in.
-Additionally, if Polaris is running somewhere other than `localhost:8181`, you can specify the correct hostname and port by providing `--host` and `--port` flags. For the full set of options supported by the CLI, please refer to the [docs]({{% relref "../command-line-interface" %}}).
+Additionally, if Polaris is running somewhere other than `localhost:8181`, you can specify the correct hostname and port by providing `--host` and `--port` flags. For the full set of options supported by the CLI, please refer to the [docs]({{% relref "../../command-line-interface" %}}).
### Creating a Principal and Assigning it Privileges
-With a catalog created, we can create a [principal]({{% relref "../entities#principal" %}}) that has access to manage that catalog. For details on how to configure the Polaris CLI, see [the section above](#defining-a-catalog) or refer to the [docs]({{% relref "../command-line-interface" %}}).
+With a catalog created, we can create a [principal]({{% relref "../../entities#principal" %}}) that has access to manage that catalog. For details on how to configure the Polaris CLI, see [the section above](#defining-a-catalog) or refer to the [docs]({{% relref "../../command-line-interface" %}}).
```shell
./polaris \
@@ -81,7 +81,7 @@ export USER_CLIENT_ID=XXXX
export USER_CLIENT_SECRET=YYYY
```
-Now, we grant the principal the [principal role]({{% relref "../entities#principal-role" %}}) we created, and grant the [catalog role]({{% relref "../entities#catalog-role" %}}) the principal role we created. For more information on these entities, please refer to the linked documentation.
+Now, we grant the principal the [principal role]({{% relref "../../entities#principal-role" %}}) we created, and grant the [catalog role]({{% relref "../../entities#catalog-role" %}}) the principal role we created. For more information on these entities, please refer to the linked documentation.
```shell
./polaris \
@@ -106,7 +106,7 @@ Now, we’ve linked our principal to the catalog via roles like so:

-In order to give this principal the ability to interact with the catalog, we must assign some [privileges]({{% relref "../entities#privilege" %}}). For the time being, we will give this principal the ability to fully manage content in our new catalog. We can do this with the CLI like so:
+In order to give this principal the ability to interact with the catalog, we must assign some [privileges]({{% relref "../../entities#privilege" %}}). For the time being, we will give this principal the ability to fully manage content in our new catalog. We can do this with the CLI like so:
```shell
./polaris \
@@ -120,7 +120,7 @@ In order to give this principal the ability to interact with the catalog, we mus
CATALOG_MANAGE_CONTENT
```
-This grants the [catalog privileges]({{% relref "../entities#privilege" %}}) `CATALOG_MANAGE_CONTENT` to our catalog role, linking everything together like so:
+This grants the [catalog privileges]({{% relref "../../entities#privilege" %}}) `CATALOG_MANAGE_CONTENT` to our catalog role, linking everything together like so:

@@ -334,7 +334,9 @@ curl -v http://127.0.0.1:8181/api/management/v1/catalogs/quickstart_catalog -H "
```
## Next Steps
-* Visit [Configuring Polaris for Production]({{% relref "../configuring-polaris-for-production" %}}).
+* Visit [Using Keycloak as the external identity provider]({{% relref "keycloak-idp" %}}).
+* Visit [Using Polaris with telemetry tools]({{% relref "telemetry-tools" %}}).
+* Visit [Configuring Polaris for Production]({{% relref "../../configuring-polaris-for-production" %}}).
* A Getting Started experience for using Spark with Jupyter Notebooks is documented [here](https://github.com/apache/polaris/blob/main/getting-started/spark/README.md).
* To shut down a locally-deployed Polaris server and clean up all related Docker containers, run the command listed below. Cloud Deployments have their respective termination commands on their Deployment page, while Polaris running on Gradle will terminate when the Gradle process terminates.
```shell
diff --git a/site/content/in-dev/unreleased/managing-security/external-idp/keycloak-idp.md b/site/content/in-dev/unreleased/getting-started/using-polaris/keycloak-idp.md
similarity index 97%
rename from site/content/in-dev/unreleased/managing-security/external-idp/keycloak-idp.md
rename to site/content/in-dev/unreleased/getting-started/using-polaris/keycloak-idp.md
index 1a9cdad484..a0d27b7386 100644
--- a/site/content/in-dev/unreleased/managing-security/external-idp/keycloak-idp.md
+++ b/site/content/in-dev/unreleased/getting-started/using-polaris/keycloak-idp.md
@@ -17,12 +17,14 @@
# specific language governing permissions and limitations
# under the License.
#
-title: Using Polaris with Keycloak as external IDP
+title: Getting Started with Apache Polaris, External Authentication and Keycloak
linkTitle: Using Keycloak IDP
type: docs
-weight: 100
+weight: 400
---
+## Overview
+
This example uses Keycloak as an **external** identity provider for Polaris. The "iceberg" realm is automatically
created and configured from the `iceberg-realm.json` file.
@@ -48,7 +50,7 @@ Polaris is configured with 3 realms:
issued by both Polaris and Keycloak.
For more information about how to configure Polaris with external authentication, see the
-[Polaris documentation]({{% ref "../external-idp" %}}).
+[IDP integration documentation]({{% relref "../../managing-security/external-idp" %}}).
## Starting the Example
diff --git a/site/content/in-dev/unreleased/getting-started/using-polaris/telemetry-tools.md b/site/content/in-dev/unreleased/getting-started/using-polaris/telemetry-tools.md
new file mode 100644
index 0000000000..b6a9e8f8eb
--- /dev/null
+++ b/site/content/in-dev/unreleased/getting-started/using-polaris/telemetry-tools.md
@@ -0,0 +1,70 @@
+---
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+title: Getting Started with Apache Polaris, Prometheus and Jaeger
+linkTitle: Using Polaris with telemetry tools
+type: docs
+weight: 401
+---
+
+This example requires `jq` to be installed on your machine.
+
+1. Build the Polaris image if it's not already present locally:
+
+ ```shell
+ ./gradlew \
+ :polaris-server:assemble \
+ :polaris-server:quarkusAppPartsBuild --rerun \
+ -Dquarkus.container-image.build=true
+ ```
+
+2. Start the docker compose group by running the following command from the root of the repository:
+
+ ```shell
+ export ASSETS_PATH=$(pwd)/getting-started/assets/
+ export CLIENT_ID=root
+ export CLIENT_SECRET=s3cr3t
+ docker compose -f getting-started/telemetry/docker-compose.yml up
+ ```
+
+3. To access Polaris from the host machine, first request an access token:
+
+ ```shell
+ export POLARIS_TOKEN=$(curl -s http://localhost:8181/api/catalog/v1/oauth/tokens \
+ --user root:s3cr3t \
+ -d 'grant_type=client_credentials' \
+ -d 'scope=PRINCIPAL_ROLE:ALL' | jq -r .access_token)
+ ```
+
+4. Then, use the access token in the Authorization header when accessing Polaris; you can also test
+ the `Polaris-Request-Id` header; you should see it in all logs and traces:
+
+ ```shell
+ curl -v 'http://localhost:8181/api/management/v1/principal-roles' \
+ -H "Authorization: Bearer $POLARIS_TOKEN" \
+ -H "Polaris-Request-Id: 1234"
+ curl -v 'http://localhost:8181/api/catalog/v1/config?warehouse=quickstart_catalog' \
+ -H "Authorization: Bearer $POLARIS_TOKEN" \
+ -H "Polaris-Request-Id: 5678"
+ ```
+
+5. Access the following services:
+
+ - Prometheus UI: browse to http://localhost:9093 to view metrics.
+ - Jaeger UI: browse to http://localhost:16686 to view traces.
diff --git a/site/content/in-dev/unreleased/managing-security/_index.md b/site/content/in-dev/unreleased/managing-security/_index.md
index d96c870c54..3a10c8900b 100644
--- a/site/content/in-dev/unreleased/managing-security/_index.md
+++ b/site/content/in-dev/unreleased/managing-security/_index.md
@@ -20,5 +20,9 @@
title: Managing Security
linkTitle: Managing Security
type: docs
-weight: 1001
+weight: 550
---
+
+## [Access Control]({{< relref "access-control" >}})
+
+## [Authentification and Identity Providers]({{< relref "external-idp" >}})
\ No newline at end of file
diff --git a/site/content/in-dev/unreleased/managing-security/external-idp/_index.md b/site/content/in-dev/unreleased/managing-security/external-idp/_index.md
index 6767924c59..0b236cf31a 100644
--- a/site/content/in-dev/unreleased/managing-security/external-idp/_index.md
+++ b/site/content/in-dev/unreleased/managing-security/external-idp/_index.md
@@ -51,7 +51,7 @@ polaris.authentication.realm2.type=mixed
### Authenticator
-The [`Authenticator`](https://github.com/apache/polaris/blob/main/service/common/src/main/java/org/apache/polaris/service/auth/Authenticator.java) is a component responsible for resolving the principal and the principal roles, and for creating a `PolarisPrincipal` from the credentials provided by the authentication process. It is a central component and is invoked for all types of authentication.
+The `Authenticator` is a component responsible for resolving the principal and the principal roles, and for creating a `PolarisPrincipal` from the credentials provided by the authentication process. It is a central component and is invoked for all types of authentication.
The `type` property is used to define the `Authenticator` implementation. It is overridable per realm:
@@ -64,7 +64,7 @@ polaris.authentication.realm1.authenticator.type=custom
### Token Broker
-The [`TokenBroker`](https://github.com/apache/polaris/blob/main/service/common/src/main/java/org/apache/polaris/service/auth/TokenBroker.java) signs and verifies tokens to ensure that they can be validated and remain unaltered.
+The `TokenBroker` signs and verifies tokens to ensure that they can be validated and remain unaltered.
```properties
polaris.authentication.token-broker.type=rsa-key-pair
@@ -138,7 +138,7 @@ quarkus.oidc.oidc-tenant1.client-id=client1
quarkus.oidc.oidc-tenant1.application-type=service
```
-When using multiple OIDC tenants, it's your responsibility to configure tenant resolution appropriately. See the [Quarkus OpenID Connect Multitenany Guide](https://quarkus.io/guides/security-openid-connect-multitenancy#tenant-resolution).
+When using multiple OIDC tenants, it's your responsibility to configure tenant resolution appropriately. See the [Quarkus OpenID Connect Multitenancy Guide](https://quarkus.io/guides/security-openid-connect-multitenancy#tenant-resolution).
### Principal Mapping
@@ -196,105 +196,6 @@ polaris.oidc.principal-roles-mapper.mappings[0].replacement=PRINCIPAL_ROLE:$1
```
See more examples below.
-
-## Developer Architecture Notes
-
-The following sections describe internal implementation details for developers who want to understand or extend Polaris authentication.
-
-### Authentication Architecture
-
-Polaris separates authentication into two logical phases using [Quarkus Security](https://quarkus.io/guides/security-overview):
-
-1. Credential extraction – parsing headers and tokens
-2. Credential authentication – validating identity and assigning roles
-
-### Key Interfaces
-
-- [`Authenticator`](https://github.com/apache/polaris/blob/main/service/common/src/main/java/org/apache/polaris/service/auth/Authenticator.java): A core interface used to authenticate credentials and resolve principal and principal roles. Roles may be derived from OIDC claims or internal mappings.
-- [`DecodedToken`](https://github.com/apache/polaris/blob/main/service/common/src/main/java/org/apache/polaris/service/auth/DecodedToken.java): Used in internal auth and inherits from `PrincipalCredential`.
-
-- The [`DefaultAuthenticator`](https://github.com/apache/polaris/blob/main/service/common/src/main/java/org/apache/polaris/service/auth/DefaultAuthenticator.java) is used to implement realm-specific logic based on these abstractions.
-
-### Token Broker Configuration
-
-When internal authentication is enabled, Polaris uses token brokers to handle the decoding and validation of authentication tokens. These brokers are request-scoped and can be configured per realm. Each realm may use its own strategy, such as RSA key pairs or shared secrets, depending on security requirements.
-
-## Developer Authentication Workflows
-
-### Internal Authentication
-
-1. [`InternalAuthenticationMechanism`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/quarkus/auth/internal/InternalAuthenticationMechanism.java) parses the auth header.
-2. Uses [`TokenBroker`](https://github.com/apache/polaris/blob/main/service/common/src/main/java/org/apache/polaris/service/auth/TokenBroker.java) to decode the token.
-3. Builds [`PrincipalAuthInfo`](https://github.com/apache/polaris/blob/main/service/common/src/main/java/org/apache/polaris/service/auth/PrincipalAuthInfo.java) and generates `SecurityIdentity` (Quarkus).
-4. `Authenticator.authenticate()` validates the credential, resolves the principal and principal roles, then creates the `PolarisPrincipal`.
-
-### External Authentication
-
-1. `OidcAuthenticationMechanism` (Quarkus) processes the auth header.
-2. [`OidcTenantResolvingAugmentor`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/quarkus/auth/external/OidcTenantResolvingAugmentor.java) selects the OIDC tenant.
-3. [`PrincipalAuthInfoAugmentor`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/quarkus/auth/external/PrincipalAuthInfoAugmentor.java) extracts JWT claims.
-4. `Authenticator.authenticate()` validates the claims, resolves the principal and principal roles, then creates the `PolarisPrincipal`.
-
-### Mixed Authentication
-
-1. [`InternalAuthenticationMechanism`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/quarkus/auth/internal/InternalAuthenticationMechanism.java) tries decoding.
-2. If successful, proceed with internal authentication.
-3. Otherwise, fall back to external (OIDC) authentication.
-
-## OIDC Configuration Reference
-
-### Principal Mapping
-
-- Interface: [`PrincipalMapper`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/quarkus/auth/external/mapping/PrincipalMapper.java)
-
- The `PrincipalMapper` is responsible for extracting the Polaris principal ID and display name from OIDC tokens.
-
-- Implementation selector:
-
- This property selects the implementation of the `PrincipalMapper` interface. The default implementation extracts fields from specific claim paths.
-
- ```properties
- polaris.oidc.principal-mapper.type=default
- ```
-
-- Configuration properties for the default implementation:
-
- ```properties
- polaris.oidc.principal-mapper.id-claim-path=polaris/principal_id
- polaris.oidc.principal-mapper.name-claim-path=polaris/principal_name
- ```
-
-- It can be overridden per OIDC tenant.
-
-### Roles Mapping
-
-- Interface: [`PrincipalRolesMapper`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/quarkus/auth/external/mapping/PrincipalRolesMapper.java)
-
- Polaris uses this component to transform role claims from OIDC tokens into Polaris roles.
-
-- Quarkus OIDC configuration:
-
- This setting instructs Quarkus on where to locate roles within the OIDC token.
-
- ```properties
- quarkus.oidc.roles.role-claim-path=polaris/roles
- ```
-
-- Implementation selector:
-
- This property selects the implementation of `PrincipalRolesMapper`. The `default` implementation applies regular expression (regex) transformations to OIDC roles.
-
- ```properties
- polaris.oidc.principal-roles-mapper.type=default
- ```
-
-- Configuration properties for the default implementation:
-
- ```properties
- polaris.oidc.principal-roles-mapper.filter=^(?!profile$|email$).*
- polaris.oidc.principal-roles-mapper.mappings[0].regex=^.*$
- polaris.oidc.principal-roles-mapper.mappings[0].replacement=PRINCIPAL_ROLE:$0
- ```
### Example JWT Mappings
@@ -348,6 +249,7 @@ When internal authentication is enabled, Polaris uses token brokers to handle th
Polaris roles: `PRINCIPAL_ROLE:service_admin` and `PRINCIPAL_ROLE:catalog_admin`
-### Additional Examples
+### Additional Links
-For complete Keycloak integration example, see: [Keycloak External IDP Configuration Guide]({{< relref "keycloak-idp.md" >}})
\ No newline at end of file
+* For complete Keycloak integration example, see: [Keycloak External IDP Configuration Guide]({{< relref "keycloak-idp.md" >}})
+* See [Developer Notes]({{< relref "idp-dev-notes.md" >}}) with internal implementation details for developers who want to understand or extend Polaris authentication.
\ No newline at end of file
diff --git a/site/content/in-dev/unreleased/managing-security/external-idp/idp-dev-notes.md b/site/content/in-dev/unreleased/managing-security/external-idp/idp-dev-notes.md
new file mode 100644
index 0000000000..16bc759b8d
--- /dev/null
+++ b/site/content/in-dev/unreleased/managing-security/external-idp/idp-dev-notes.md
@@ -0,0 +1,122 @@
+---
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+title: Authentification Development Details
+linkTitle: Development Details
+type: docs
+weight: 301
+---
+
+## Developer Architecture Notes
+
+### Authentication Architecture
+
+Polaris separates authentication into two logical phases using [Quarkus Security](https://quarkus.io/guides/security-overview):
+
+1. Credential extraction – parsing headers and tokens
+2. Credential authentication – validating identity and assigning roles
+
+### Key Interfaces
+
+- [`Authenticator`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/auth/Authenticator.java): A core interface used to authenticate credentials and resolve principal and principal roles. Roles may be derived from OIDC claims or internal mappings.
+- [`InternalPolarisToken`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/auth/InternalPolarisToken.java): Used in internal auth and inherits from `PrincipalCredential`.
+
+- The [`DefaultAuthenticator`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/auth/DefaultAuthenticator.java) is used to implement realm-specific logic based on these abstractions.
+
+### Token Broker Configuration
+
+When internal authentication is enabled, Polaris uses [`TokenBroker`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/auth/TokenBroker.java) to handle the decoding and validation of authentication tokens. These brokers are request-scoped and can be configured per realm. Each realm may use its own strategy, such as RSA key pairs or shared secrets, depending on security requirements.
+See [Token Broker description]({{< relref "../external-idp#token-broker" >}}) for configuration details.
+
+## Developer Authentication Workflows
+
+### Internal Authentication
+
+1. [`InternalAuthenticationMechanism`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/auth/internal/InternalAuthenticationMechanism.java) parses the auth header.
+2. Uses [`TokenBroker`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/auth/TokenBroker.java) to decode the token.
+3. Builds [`InternalAuthenticationRequest`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/auth/internal/InternalAuthenticationRequest.java) and generates `SecurityIdentity` (Quarkus).
+4. `Authenticator.authenticate()` validates the credential, resolves the principal and principal roles, then creates the `PolarisPrincipal`.
+
+### External Authentication
+
+1. `OidcAuthenticationMechanism` (Quarkus) processes the auth header.
+2. [`OidcTenantResolvingAugmentor`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/auth/external/tenant/OidcTenantResolvingAugmentor.java) selects the OIDC tenant.
+3. [`OidcPolarisCredentialAugmentor`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/auth/external/OidcPolarisCredentialAugmentor.java) extracts JWT claims.
+4. `Authenticator.authenticate()` validates the claims, resolves the principal and principal roles, then creates the `PolarisPrincipal`.
+
+### Mixed Authentication
+
+1. [`InternalAuthenticationMechanism`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/auth/internal/InternalAuthenticationMechanism.java) tries decoding.
+2. If successful, proceed with internal authentication.
+3. Otherwise, fall back to external (OIDC) authentication.
+
+## OIDC Configuration Reference
+
+### Principal Mapping
+
+- Interface: [`PrincipalMapper`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/auth/external/mapping/PrincipalMapper.java)
+
+ The `PrincipalMapper` is responsible for extracting the Polaris principal ID and display name from OIDC tokens.
+
+- Implementation selector:
+
+ This property selects the implementation of the `PrincipalMapper` interface. The default implementation extracts fields from specific claim paths.
+
+ ```properties
+ polaris.oidc.principal-mapper.type=default
+ ```
+
+- Configuration properties for the default implementation:
+
+ ```properties
+ polaris.oidc.principal-mapper.id-claim-path=polaris/principal_id
+ polaris.oidc.principal-mapper.name-claim-path=polaris/principal_name
+ ```
+
+- It can be overridden per OIDC tenant.
+
+### Roles Mapping
+
+- Interface: [`PrincipalRolesMapper`](https://github.com/apache/polaris/blob/main/runtime/service/src/main/java/org/apache/polaris/service/auth/external/mapping/PrincipalRolesMapper.java)
+
+ Polaris uses this component to transform role claims from OIDC tokens into Polaris roles.
+
+- Quarkus OIDC configuration:
+
+ This setting instructs Quarkus on where to locate roles within the OIDC token.
+
+ ```properties
+ quarkus.oidc.roles.role-claim-path=polaris/roles
+ ```
+
+- Implementation selector:
+
+ This property selects the implementation of `PrincipalRolesMapper`. The `default` implementation applies regular expression (regex) transformations to OIDC roles.
+
+ ```properties
+ polaris.oidc.principal-roles-mapper.type=default
+ ```
+
+- Configuration properties for the default implementation:
+
+ ```properties
+ polaris.oidc.principal-roles-mapper.filter=^(?!profile$|email$).*
+ polaris.oidc.principal-roles-mapper.mappings[0].regex=^.*$
+ polaris.oidc.principal-roles-mapper.mappings[0].replacement=PRINCIPAL_ROLE:$0
+ ```
diff --git a/site/content/in-dev/unreleased/telemetry.md b/site/content/in-dev/unreleased/telemetry.md
index 9e867408da..13b2823789 100644
--- a/site/content/in-dev/unreleased/telemetry.md
+++ b/site/content/in-dev/unreleased/telemetry.md
@@ -190,3 +190,7 @@ polaris.log.mdc.region=us-west-2
```
MDC context is propagated across threads, including in `TaskExecutor` threads.
+
+## Links
+
+Visit [Using Polaris with telemetry tools]({{% relref "telemetry-tools" %}}) to see sample Polaris config with Prometheus and Jaeger.