This guide covers configuring OIDC-based STS federation using Keycloak as the identity provider. It follows the same process as the Azure Entra ID guide, highlighting differences where they occur.
Prerequisite: Read the main OIDC S3 Federation Guide first. This document only covers Keycloak-specific differences.
Concept Mapping: Azure vs Keycloak
Concept | Azure Entra ID | Keycloak |
|---|---|---|
Identity provider instance | Azure Tenant | Realm |
Application definition | App Registration | Client |
Application identifier | Application (Client) ID | Client ID |
User directory | Azure AD | Realm Users |
Admin interface | Azure Portal | Keycloak Admin Console |
Configuration Variables (Keycloak)
# Keycloak Configuration
KEYCLOAK_HOST="keycloak.example.com"
KEYCLOAK_REALM="vast-federation"
KEYCLOAK_CLIENT_ID="vast-oidc-client"
# VAST Configuration (same as Azure guide)
VAST_TENANT_NAME="<your-vast-tenant-name>"
VAST_TENANT_ID=<your-vast-tenant-id>
VAST_VIP="<your-vast-vip-address>"Step 1: Create Keycloak Client
Parallels Azure Step 1: Create App Registration
1.1 Access Keycloak Admin Console
Navigate to: <https://<KEYCLOAK_HOST>>/admin/
Log in with admin credentials.
1.2 Select or Create a Realm
From the realm dropdown (top-left), select your realm or create a new one
Note the realm name - this is your
KEYCLOAK_REALM
Validate: Realm name appears in the top-left dropdown.
1.3 Create a Client
Navigate to Clients → Create client
Set the following:
Client type: OpenID Connect
Client ID:
vast-oidc-client(this is yourKEYCLOAK_CLIENT_ID)
Click Next
1.4 Configure Client Authentication
Client authentication: OFF (public client, like Azure's public client flow)
Authorization: OFF
Authentication flow: Check Standard flow and Direct access grants
Click Next, then Save
Validate: Client appears in the Clients list.
Azure equivalent: This is similar to enabling "public client flows" (
--is-fallback-public-client true) in Azure.
1.5 Enable Device Code Flow (Optional)
If you want to use device code flow (like Azure's device login):
Navigate to Realm settings → Login
Enable OAuth 2.0 Device Authorization Grant
Alternatively, use Direct Access Grants (resource owner password) for testing.
1.6 Record the Discovery URL
https://<KEYCLOAK_HOST>/realms/<KEYCLOAK_REALM>/.well-known/openid-configurationValidate: Open this URL in a browser - you should see JSON with issuer, authorization_endpoint, jwks_uri.
Key difference from Azure:
Azure:
<https://login.microsoftonline.com/<TENANT>>/v2.0/.well-known/openid-configurationKeycloak:
<https://<KEYCLOAK_HOST>>/realms/<REALM>/.well-known/openid-configuration
Step 2: Create OIDC Provider on VAST
Same process as Azure, different URL
vcli: admin> oidc create \
--name "keycloak-oidc" \
--discovery-url "https://<KEYCLOAK_HOST>/realms/<KEYCLOAK_REALM>/.well-known/openid-configuration" \
--user-jwt-attribute "email"Validate: vcli: oidc list shows State = OK
Note: Keycloak must be reachable from the VAST cluster. If using self-signed certificates, ensure VAST trusts the CA.
Steps 3-5: VAST Configuration
Identical to the Azure guide
Step 3: Associate OIDC Provider with Tenant (Web UI)
Step 4: Ensure Tenant Has a VIP Pool
Step 5: Create Identity Policy
No changes needed - follow the main guide.
Step 6: Create IAM Role with Trust Policy
Same process, different iss format
The trust policy must match Keycloak's iss claim format:
Provider |
| Trust policy |
|---|---|---|
Azure v2.0 |
|
|
Keycloak |
|
|
6.1 Create the IAM Role
vcli: admin> iamrole create \
--name "keycloak-s3-role" \
--tenant-id <VAST_TENANT_ID> \
--description "Role for Keycloak OIDC federated S3 access" \
--identity-policies-ids <IDENTITY_POLICY_ID> \
--trust-policy '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Federated":"oidc-provider/<KEYCLOAK_HOST>/realms/<KEYCLOAK_REALM>"},"Action":"sts:AssumeRoleWithWebIdentity","Condition":{"StringEquals":{"<KEYCLOAK_HOST>/realms/<KEYCLOAK_REALM>:aud":"<KEYCLOAK_CLIENT_ID>"}}}]}'Example with real values:
vcli: admin> iamrole create \
--name "keycloak-s3-role" \
--tenant-id 1 \
--description "Role for Keycloak OIDC federated S3 access" \
--identity-policies-ids 5 \
--trust-policy '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Federated":"oidc-provider/keycloak.example.com/realms/vast-federation"},"Action":"sts:AssumeRoleWithWebIdentity","Condition":{"StringEquals":{"keycloak.example.com/realms/vast-federation:aud":"vast-oidc-client"}}}]}'Step 7: Create S3 Bucket
Identical to the Azure guide
No changes needed - follow the main guide.
Step 8: Authenticate and Get JWT Token
Different authentication endpoints
Option A: Direct Access Grants (Password Flow)
This is the simplest method for testing (requires user credentials):
curl -s -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=<KEYCLOAK_CLIENT_ID>" \
-d "username=<USERNAME>" \
-d "password=<PASSWORD>" \
-d "grant_type=password" \
-d "scope=openid" \
"https://<KEYCLOAK_HOST>/realms/<KEYCLOAK_REALM>/protocol/openid-connect/token"Validate: Response contains id_token, access_token, etc.
Extract the id_token:
echo "$TOKEN_RESPONSE" | jq -r .id_token > /tmp/jwt_token.txtOption B: Device Code Flow
If device authorization is enabled in Keycloak:
8.1 Request device code:
curl -s -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=<KEYCLOAK_CLIENT_ID>" \
-d "scope=openid" \
"https://<KEYCLOAK_HOST>/realms/<KEYCLOAK_REALM>/protocol/openid-connect/auth/device"Validate: Response contains device_code, user_code, verification_uri.
8.2 User authenticates:
Open the
verification_uriin a browserEnter the
user_codeLog in and approve
8.3 Exchange for token:
curl -s -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=<KEYCLOAK_CLIENT_ID>" \
-d "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
-d "device_code=<DEVICE_CODE>" \
"https://<KEYCLOAK_HOST>/realms/<KEYCLOAK_REALM>/protocol/openid-connect/token"8.4 Verify Token Claims
cat /tmp/jwt_token.txt | cut -d'.' -f2 | base64 -d 2>/dev/null | jq .Validate that these claims match your configuration:
Claim | Expected Value |
|---|---|
|
|
|
|
| Unix timestamp in the future |
Key difference from Azure:
Azure
iss:<https://login.microsoftonline.com/<TENANT>>/v2.0Keycloak
iss:<https://<KEYCLOAK_HOST>>/realms/<REALM>
Steps 9-10: Assume Role and Test S3
Same process, different role ARN
9.1 Assume Role
aws sts assume-role-with-web-identity \
--duration-seconds 900 \
--role-arn "arn:vast::<VAST_TENANT_NAME>:role/keycloak-s3-role" \
--role-session-name "keycloak-test" \
--web-identity-token "$(cat /tmp/jwt_token.txt)" \
--endpoint-url "https://<VAST_VIP>" \
--no-verify-ssl9.2 Export and Test
Follow the main guide Steps 9.2-9.3 and Step 10 - the process is identical once you have the STS credentials.
Keycloak-Specific Troubleshooting
"InvalidIdentityToken" with Keycloak
Common causes:
Self-signed certificate not trusted
If Keycloak uses a self-signed cert, VAST may fail to fetch the JWKS.
Check:
vcli: oidc list- if State is notOK, there may be a certificate issue.audclaim doesn't matchKeycloak's default
audclaim contains the client ID. Verify:cat /tmp/jwt_token.txt | cut -d'.' -f2 | base64 -d 2>/dev/null | jq '.aud'This might be a string or an array. The trust policy condition must match exactly.
Realm name case sensitivity
Keycloak realm names are case-sensitive. Ensure the realm name in your discovery URL and trust policy match exactly.
Keycloak Token Lifetime
Configure token lifetimes in Keycloak Admin Console:
Navigate to Realm settings → Tokens
Adjust:
Access Token Lifespan: Default 5 minutes (consider increasing for testing).
SSO Session Idle: How long before re-authentication is required.
Quick Reference: Azure vs Keycloak
Configuration Item | Azure Entra ID | Keycloak |
|---|---|---|
Discovery URL |
|
|
|
|
|
| Azure App ID (GUID) | Keycloak Client ID (string) |
Trust policy principal |
|
|
Device code endpoint |
|
|
Token endpoint |
|
|
Public client setting |
| Client authentication = OFF |
Admin interface | Azure Portal | Keycloak Admin Console |