Configure MinIO for Authentication using Keycloak
Overview
This procedure configures MinIO to use Keycloak as an external IDentity Provider (IDP) for authentication of users via the OpenID Connect (OIDC) protocol.
This procedure specifically covers the following steps:
Deploy a Keycloak and MinIO Container
Configure Keycloak for use with MinIO authentication and authorization
Configure MinIO to use Keycloak as the OIDC provider
Create policies to control access of Keycloak-authenticated users
Log into the MinIO Console using SSO and a Keycloak-managed identity
Generate temporary S3 access credentials using the
AssumeRoleWithWebIdentity
Security Token Service (STS) API
This procedure was written and tested against Keycloak 21.0.0
.
The provided instructions may work against other Keycloak versions.
This procedure assumes you have prior experience with Keycloak and have reviewed their documentation for guidance and best practices in deploying, configuring, and managing the service.
Prerequisites
MinIO Deployment
This procedure assumes an existing MinIO cluster running the latest stable MinIO version. Refer to the Install and Deploy MinIO for more complete documentation on new MinIO deployments.
This procedure may work as expected for older versions of MinIO.
Install and Configure mc
with Access to the MinIO Cluster
This procedure uses mc
for performing operations on the MinIO cluster.
Install mc
on a machine with network access to the cluster.
See the mc
Installation Quickstart for instructions on downloading and installing mc
.
This procedure assumes a configured alias
for the MinIO cluster.
Configure MinIO for Keycloak Identity Management
1) Create the Podman Pod
Create a Podman Pod to deploy the Keycloak and MinIO containers in a Pod with shared networking. This ensures both containers can communicate normally.
podman pod create \
-p 9000:9000 -p 9001:9001 -p 8080:8080 \
-v ~/minio-keycloak/minio:/mnt/minio \
-n minio-keycloak
Replace ~/minio-keycloak/minio
with a path to an empty folder in which the MinIO container stores data.
You can alternatively deploy the Containers as Root to allow access to the host network for the purpose of inter-container networking.
Deploying via Docker Compose is out of scope for this tutorial.
2) Start the Keycloak Container
Follow the instructions for running Keycloak in a container. The Try Keycloak in development mode steps are sufficient for this procedure.
podman run -dt \
--name keycloak \
--pod minio-keycloak \
-e KEYCLOAK_ADMIN=keycloakadmin \
-e KEYCLOAK_ADMIN_PASSWORD=keycloakadmin123 \
quay.io/keycloak/keycloak:latest start-dev
Go to localhost:8080
to access the Keycloak container.
3) Configure or Create a Client for Accessing Keycloak
Authenticate to the Keycloak Administrative Console and navigate to Clients.
Select Create client and follow the instructions to create a new Keycloak client for MinIO. Fill in the specified inputs as follows:
Client ID |
Set to a unique identifier for MinIO ( |
---|---|
Client type |
Set to |
Always display in console |
Toggle to |
Client authentication |
Toggle to |
Authentication flow |
Toggle on |
(Optional) Authentication flow |
Toggle on |
Keycloak deploys the client with a default set of configuration values. Modify these values as necessary for your Keycloak setup and desired behavior. The following table provides a baseline of settings and values to configure:
Root URL |
Set to |
---|---|
Home URL |
Set to the Realm you want MinIO to use ( |
Valid Redirect URI |
Set to |
Keys -> Use JWKS URL |
Toggle to |
Advanced -> Advanced Settings -> Access Token Lifespan |
Set to |
4) Create Client Scope for MinIO Client
Client scopes allow Keycloak to map user attributes as part of the JSON Web Token (JWT) returned in authentication requests. This allows MinIO to reference those attributes when assigning policies to the user. This step creates the necessary client scope to support MinIO authorization after successful Keycloak authentication.
Navigate to the Client scopes view and create a new client scope for MinIO authorization:
Name |
Set to any recognizable name for the policy ( |
---|---|
Include in token scope |
Toggle to |
Once created, select the scope from the list and navigate to Mappers.
Select Configure a new mapper to create a new mapping:
User Attribute |
Select the Mapper Type |
---|---|
Name |
Set to any recognizable name for the mapping ( |
User Attribute |
Set to |
Token Claim Name |
Set to |
Add to ID token |
Set to |
Claim JSON Type |
Set to |
Multivalued |
Set to This allows setting multiple |
Aggregate attribute values |
Set to This allows users to inherit any |
Once created, assign the Client Scope to the MinIO client.
Navigate to Clients and select the MinIO client.
Select Client scopes, then select Add client scope.
Select the previously created scope and set the Assigned type to
default
.
5) Apply the Necessary Attribute to Keycloak Users/Groups
You must assign an attribute named policy
to the Keycloak Users or Groups.
Set the value to any policy on the MinIO deployment.
For Users, navigate to Users and select or create the User:
Credentials |
Set the user password to a permanent value if not already set |
---|---|
Attributes |
Create a new attribute with key |
For Groups, navigate to Groups and select or create the Group:
Attributes |
Create a new attribute with key |
---|
You can assign users to groups such that they inherit the specified policy
attribute.
If you set the Mapper settings to enable Aggregate attribute values, Keycloak includes the aggregated array of policies as part of the authenticated user’s JWT token.
MinIO can use this list of policies when authorizing the user.
You can test the configured policies of a user by using the Keycloak API:
curl -d "client_id=minio" \
-d "client_secret=secretvalue" \
-d "grant_type=password" \
-d "username=minio-user-1" \
-d "password=minio-user-1-password" \
http://localhost:8080/realms/REALM/protocol/openid-connect/token
If successful, the access_token
contains the JWT necessary to use the MinIO AssumeRoleWithWebIdentity STS API and generate S3 credentials.
You can use a JWT decoder to review the payload and ensure it contains the policy
key with one or more MinIO policies listed.
6) Start the MinIO Container
The following command starts the MinIO Container and attaches it to the minio-keycloak
pod.
podman run -dt \
--name minio-server \
--pod minio-keycloak \
quay.io/minio/minio:RELEASE.2023-02-22T18-23-45Z server /mnt/data --console-address :9001
Go to localhost:9001
to access the MinIO Console.
Log in using the default credentials minioadmin:minioadmin
.
7) Configure MinIO for Keycloak Authentication
MinIO supports multiple methods for configuring Keycloak authentication:
Using the MinIO Console
Using a terminal/shell and the
mc idp openid
commandUsing environment variables set prior to starting MinIO
Log in as a user with administrative privileges for the MinIO deployment such as a user with the consoleAdmin
policy.
Select Identity from the left-hand navigation bar, then select OpenID. Select Create Configuration to create a new configuration.
Enter the following information into the modal:
Name |
Enter a unique name for the Keycloak instance |
---|---|
Config URL |
Specify the address of the Keycloak OpenID configuration document (localhost:8080) Ensure the |
Client ID |
Specify the name of the Keycloak client created in Step 1 |
Client Secret |
Specify the secret credential value for the Keycloak client created in Step 1 |
Display Name |
Specify the user-facing name the MinIO Console displays as part of the Single-Sign On (SSO) workflow for the configured Keycloak service |
Scopes |
Specify the OpenID scopes to include in the JWT, such as You can reference these scopes using supported OpenID policy variables for the purpose of programmatic policy . |
Redirect URI Dynamic |
Toggle to Substitutes the MinIO Console address used by the client as part of the Keycloak redirect URI. Keycloak returns authenticated users to the Console using the provided URI. For MinIO Console deployments behind a reverse proxy, load balancer, or similar network control plane, you can instead use the |
Select Save to apply the configuration.
You can use the mc idp openid add
command to create a new configuration for the Keycloak service.
The command takes all supported OpenID Configuration Settings:
mc idp openid add ALIAS PRIMARY_IAM \
client_id=MINIO_CLIENT \
client_secret=MINIO_CLIENT_SECRET \
config_url="https://localhost:8080/realms/REALM/.well-known/openid-configuration" \
display_name="SSO_IDENTIFIER"
scopes="openid,email,preferred_username" \
redirect_uri_dynamic="on"
|
Set to a unique identifier for the Keycloak service, such as |
---|---|
MINIO_CLIENT MINIO_CLIENT_SECRET |
Set to the Keycloak client ID and secret configured in Step 1 |
|
Set to the address of the Keycloak OpenID configuration document (localhost:8080) |
|
Set to a user-facing name the MinIO Console displays as part of the Single-Sign On (SSO) workflow for the configured Keycloak service |
|
Set to a list of OpenID scopes you want to include in the JWT, such as |
|
Set to Substitutes the MinIO Console address used by the client as part of the Keycloak redirect URI. Keycloak returns authenticated users to the Console using the provided URI. For MinIO Console deployments behind a reverse proxy, load balancer, or similar network control plane, you can instead use the |
Set the following environment variables prior to starting the container using the -e ENVVAR=VALUE
flag.
The following example code sets the minimum required environment variables related to configuring Keycloak as an external identity management provider.
MINIO_IDENTITY_OPENID_CONFIG_URL_PRIMARY_IAM="https://localhost:8080/.well-known/openid-configuration"
MINIO_IDENTITY_OPENID_CLIENT_ID_PRIMARY_IAM="MINIO_CLIENT"
MINIO_IDENTITY_OPENID_CLIENT_SECRET_PRIMARY_IAM="MINIO_CLIENT_SECRET"
MINIO_IDENTITY_OPENID_DISPLAY_NAME_PRIMARY_IAM="SSO_IDENTIFIER"
MINIO_IDENTITY_OPENID_SCOPES_PRIMARY_IAM="openid,email,preferred_username"
MINIO_IDENTITY_OPENID_REDIRECT_URI_DYNAMIC_PRIMARY_IAM="on"
|
Replace the suffix You can omit the suffix if you intend to only configure a single OIDC provider for the deployment. |
---|---|
Specify the address of the Keycloak OpenID configuration document (localhost:8080) Ensure the |
|
Specify the Keycloak client ID and secret configured in Step 1 |
|
Specify the user-facing name the MinIO Console displays as part of the Single-Sign On (SSO) workflow for the configured Keycloak service |
|
Specify the OpenID scopes you want to include in the JWT, such as |
|
Set to Substitutes the MinIO Console address used by the client as part of the Keycloak redirect URI. Keycloak returns authenticated users to the Console using the provided URI. For MinIO Console deployments behind a reverse proxy, load balancer, or similar network control plane, you can instead use the |
For complete documentation on these variables, see OpenID Identity Management Settings
You must restart the MinIO deployment for the changes to apply.
Check the MinIO server logs and verify that startup succeeded with no errors related to the Keycloak configuration.
If you attempt to log in with the Console, you should now see an (SSO) button using the configured Display Name.
Specify a configured user and attempt to log in. MinIO should automatically redirect you to the Keycloak login entry. Upon successful authentication, Keycloak should redirect you back to the MinIO Console.
8) Generate Application Credentials using the Security Token Service (STS)
Applications using an S3-compatible SDK must specify credentials in the form of an access key and secret key. The MinIO AssumeRoleWithWebIdentity API returns the necessary temporary credentials, including a required session token, using a JWT returned by Keycloak after authentication.
You can test this workflow using the following sequence of HTTP calls and the curl
utility:
Authenticate as a Keycloak user and retrieve the JWT token
curl -X POST "https://localhost:8080/realms/REALM/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=USER" \ -d "password=PASSWORD" \ -d "grant_type=password" \ -d "client_id=CLIENT" \ -d "client_secret=SECRET"
Replace the
USER
andPASSWORD
with the credentials of a Keycloak user on theREALM
.Replace the
CLIENT
andSECRET
with the client ID and secret for the MinIO-specific Keycloak client on theREALM
You can process the results using
jq
or a similar JSON-formatting utility. Extract theaccess_token
field to retrieve the necessary access token. Pay attention to theexpires_in
field to note the number of seconds before the token expires.Generate MinIO Credentials using the
AssumeRoleWithWebIdentity
APIcurl -X POST "https://localhost:9000" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "Action=AssumeRoleWithWebIdentity" \ -d "Version=2011-06-15" \ -d "DurationSeconds=86000" \ -d "WebIdentityToken=TOKEN"
Replace the
TOKEN
with theaccess_token
value returned by Keycloak.The API returns an XML document on success containing the following keys:
Credentials.AccessKeyId
- the Access Key for the Keycloak UserCredentials.SecretAccessKey
- the Secret Key for the Keycloak UserCredentials.SessionToken
- the Session Token for the Keycloak UserCredentials.Expiration
- the Expiration Date for the generated credentials
Test the Credentials
Use your preferred S3-compatible SDK to connect to MinIO using the generated credentials.
For example, the following Python code using the MinIO Python SDK connects to the MinIO deployment and returns a list of buckets:
from minio import Minio client = MinIO( "localhost:9000", access_key = "ACCESS_KEY", secret_key = "SECRET_KEY", session_token = "SESSION_TOKEN" secure = True ) client.list_buckets()
Next Steps
Applications should implement the STS flow using their SDK of choice. When STS credentials expire, applications should have logic in place to regenerate the JWT token, STS token, and MinIO credentials before retrying and continuing operations.
Alternatively, users can generate access keys through the MinIO Console for the purpose of creating long-lived API-key like access using their Keycloak credentials.
Enable the Keycloak Admin REST API
MinIO supports using the Keycloak Admin REST API for checking if an authenticated user exists and is enabled on the Keycloak realm. This functionality allows MinIO to more quickly remove access from previously authenticated Keycloak users. Without this functionality, the earliest point in time that MinIO could disable access for a disabled or removed user is when the last retrieved authentication token expires.
This procedure assumes an existing MinIO deployment configured with Keycloak as an external identity manager.
1) Create the Necessary Client Scopes
Navigate to the Client scopes view and create a new scope:
Name |
Set to a recognizable name for the scope ( |
---|---|
Mappers |
Select Configure a new mapper |
Audience |
Set the Name to any recognizable name for the mapping ( |
Included Client Audience |
Set to |
Navigate to Clients and select the MinIO client
From Service account roles, select Assign role and assign the
admin
roleFrom Client scopes, select Add client scope and add the previously created scope
Navigate to Settings and ensure Authentication flow includes Service accounts roles
.
2) Validate Admin API Access
You can validate the functionality by using the Admin REST API with the MinIO client credentials to retrieve a bearer token and user data:
Retrieve the bearer token:
curl -d "client_id=minio" \ -d "client_secret=secretvalue" \ -d "grant_type=password" \ http://keycloak-url:port/admin/realms/REALM/protocol/openid-connect/token
Use the value returned as the
access_token
to access the Admin API:curl -H "Authentication: Bearer ACCESS_TOKEN_VALUE" \ http://keycloak-url:port/admin/realms/REALM/users/UUID
Replace
UUID
with the unique ID for the user which you want to retrieve. The response should resemble the following:{ "id": "954de141-781b-4eaf-81bf-bf3751cdc5f2", "createdTimestamp": 1675866684976, "username": "minio-user-1", "enabled": true, "totp": false, "emailVerified": false, "firstName": "", "lastName": "", "attributes": { "policy": [ "readWrite" ] }, "disableableCredentialTypes": [], "requiredActions": [], "notBefore": 0, "access": { "manageGroupMembership": true, "view": true, "mapRoles": true, "impersonate": true, "manage": true } }
MinIO would revoke access for an authenticated user if the returned value has
enabled: false
ornull
(user was removed from Keycloak).
3) Enable Keycloak Admin Support on MinIO
MinIO supports multiple methods for configuring Keycloak Admin API Support:
Using a terminal/shell and the
mc idp openid
commandUsing environment variables set prior to starting MinIO
You can use the mc idp openid update
command to modify the configuration settings for an existing Keycloak service.
You can alternatively include the following configuration settings when setting up Keycloak for the first time.
The command takes all supported OpenID Configuration Settings:
mc idp openid update ALIAS KEYCLOAK_IDENTIFIER \
vendor="keycloak" \
keycloak_admin_url="https://keycloak-url:port/admin"
keycloak_realm="REALM"
Replace
KEYCLOAK_IDENTIFIER
with the name of the configured Keycloak IDP. You can usemc idp openid ls
to view all configured IDP configurations on the MinIO deploymentSpecify the Keycloak admin URL in the
keycloak_admin_url
configuration settingSpecify the Keycloak Realm name in the
keycloak_realm
Set the following environment variables in the appropriate configuration location, such as /etc/default/minio
.
The following example code sets the minimum required environment variables related to enabling the Keycloak Admin API for an existing Keycloak configuration.
Replace the suffix _PRIMARY_IAM
with the unique identifier for the target Keycloak configuration.
MINIO_IDENTITY_OPENID_VENDOR_PRIMARY_IAM="keycloak"
MINIO_IDENTITY_OPENID_KEYCLOAK_ADMIN_URL_PRIMARY_IAM="https://keycloak-url:port/admin"
MINIO_IDENTITY_OPENID_KEYCLOAK_REALM_PRIMARY_IAM="REALM"
Specify the Keycloak admin URL in the
MINIO_IDENTITY_OPENID_KEYCLOAK_ADMIN_URL
Specify the Keycloak Realm name in the
MINIO_IDENTITY_OPENID_KEYCLOAK_REALM