Keycloak
Let users authenticate with your app by setting up Keycloak.
You can install an OpenID Connect (OIDC) identity provider (IdP) such as Keycloak in your cluster. Then, configure the Gloo Gateway external auth server with the OIDC details. You can adapt these steps for other IdPs.
This feature is an Enterprise-only feature that requires a Gloo Gateway Enterprise license.
Before you begin
Consider increasing the default timeout of the external auth server. When you set up OAuth, the external auth server must communicate with the external OIDC provider’s authorization server. Because of this interaction, the OIDC flow might take longer than the default timeout of 200ms
. In such cases, you might noticed failed requests or unexpected behavior. You can increase the default timeout by setting the requestTimeout
value on the external auth settings. The external auth settings can be configured on the Gloo Gateway Settings object.
Follow the Get started guide to install Gloo Gateway, set up a gateway resource, and deploy the httpbin sample app.
Get the external address of the gateway and save it in an environment variable.
Step 1: Install Keycloak
You might want to test how to restrict access to your applications to authenticated users, such as with external auth or JWT policies. You can install Keycloak in your cluster as an OpenID Connect (OIDC) provider.
The following steps install Keycloak in your cluster, and configure two user credentials as follows.
- Username:
user1
, password:password
, email:user1@example.com
- Username:
user2
, password:password
, email:user2@solo.io
Install and configure Keycloak:
Create a namespace for your Keycloak deployment.
kubectl create namespace keycloak
Create the Keycloak deployment.
kubectl -n keycloak apply -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/oidc/keycloak.yaml
Wait for the Keycloak rollout to finish.
kubectl -n keycloak rollout status deploy/keycloak
Set the Keycloak endpoint details from the load balancer service.
export ENDPOINT_KEYCLOAK=$(kubectl -n keycloak get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].*}'):8080 export HOST_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK} | cut -d: -f1) export PORT_KEYCLOAK=$(echo ${ENDPOINT_KEYCLOAK} | cut -d: -f2) export KEYCLOAK_URL=http://${ENDPOINT_KEYCLOAK} echo $KEYCLOAK_URL
Set the Keycloak admin token. If you see a parsing error, try running the
curl
command by itself. You might notice that your internet provider or network rules are blocking the requests. If so, you can update your security settings or change the network so that the request can be processed.export KEYCLOAK_TOKEN=$(curl -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) echo $KEYCLOAK_TOKEN
Use the admin token to configure Keycloak with the two users for testing purposes. If you get a
401 Unauthorized
error, run the previous command and try again.# Create initial token to register the client read -r client token <<<$(curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: application/json" -d '{"expiration": 0, "count": 1}' $KEYCLOAK_URL/admin/realms/master/clients-initial-access | jq -r '[.id, .token] | @tsv') export KEYCLOAK_CLIENT=${client} echo $KEYCLOAK_CLIENT # Register the client read -r id secret <<<$(curl -k -X POST -d "{ \"clientId\": \"${KEYCLOAK_CLIENT}\" }" -H "Content-Type:application/json" -H "Authorization: bearer ${token}" ${KEYCLOAK_URL}/realms/master/clients-registrations/default| jq -r '[.id, .secret] | @tsv') export KEYCLOAK_SECRET=${secret} echo $KEYCLOAK_SECRET # Add allowed redirect URIs curl -k -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X PUT -H "Content-Type: application/json" -d '{"serviceAccountsEnabled": true, "directAccessGrantsEnabled": true, "authorizationServicesEnabled": true, "redirectUris": ["*"]}' $KEYCLOAK_URL/admin/realms/master/clients/${id} # Add the group attribute in the JWT token returned by Keycloak curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: application/json" -d '{"name": "group", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-attribute-mapper", "config": {"claim.name": "group", "jsonType.label": "String", "user.attribute": "group", "id.token.claim": "true", "access.token.claim": "true"}}' $KEYCLOAK_URL/admin/realms/master/clients/${id}/protocol-mappers/models # Create first user curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: application/json" -d '{"username": "user1", "email": "user1@example.com", "enabled": true, "attributes": {"group": "users"}, "credentials": [{"type": "password", "value": "password", "temporary": false}]}' $KEYCLOAK_URL/admin/realms/master/users # Create second user curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: application/json" -d '{"username": "user2", "email": "user2@solo.io", "enabled": true, "attributes": {"group": "users"}, "credentials": [{"type": "password", "value": "password", "temporary": false}]}' $KEYCLOAK_URL/admin/realms/master/users
Open the Keycloak frontend.
open $KEYCLOAK_URL
Log in to the admin console, and enter
admin
as the username andadmin
as your password.In the Keycloak admin console, go to Users, and verify that the users that created earlier are displayed. You might need to click on View all users to see them.
In the Keycloak admin console, go to Clients, and verify that you can see a client ID that equals the output of
$KEYCLOAK_CLIENT
.
Step 2: Configure Keycloak
Now that you installed Keycloak and set up clients to use, configure Keycloak for certain OAuth use cases. The following instructions assume that you are still logged into the Administration Console from the previous step.
You might integrate OIDC with your apps. In such cases, you might need particular details from the OIDC provider to fully set up your apps. To use Keycloak for OAuth protection of these apps, you need certain settings and information from Keycloak.
- For authorization code OAuth: Confirm that you have the following environmental variables set. If not, refer to the Before you begin and Step 1: Install Keycloak sections.
echo $CLUSTER_NAME echo $INGRESS_GW_IP echo $KEYCLOAK_CLIENT echo $KEYCLOAK_URL
- For access token validation: Get a JWKS URI to use for an inline OAuth policy.
- From the sidebar menu options, click Realm Settings.
- From the General tab, scroll down to the Endpoints section and open the OpenID Endpoint Configuration link. In a new tab, your browser opens to a URL similar to
http://$KEYCLOAK_URL:8080/realms/master/.well-known/openid-configuration
- In the OpenID configuration, search for the
token_endpoint
field. Save the value as an environment variable, such as the following example.export KEYCLOAK_TOKEN_ENDPOINT=$KEYCLOAK_URL/realms/master/protocol/openid-connect/token
- In the OpenID configuration, search for the
jwks_uri
field, and copy this value, similar tohttp://$KEYCLOAK_URL:8080/realms/master/protocol/openid-connect/certs
.export KEYCLOAK_JWKS_URI=<jwks_uri>
- In a new browser tab, open the
jwks_uri
that you previously copied. - Copy and save the entire value of these keys as an environment variable.
export KEYCLOAK_CERT_KEYS={"keys":[{"kid":"_YYA...","kty":"RSA","alg":"RSA-OAEP","use":"enc","n":"r4AXlC9sR..."}]}
- For the developer portal: Configure your Keycloak client with the appropriate settings for the developer portal frontend authentication.
- From the sidebar menu options, click Clients.
- Click the Client ID that matches the
$KEYCLOAK_CLIENT
that you previously set. - From the client Settings tab, find the Access settings and update the following fields.
- Valid redirect URIs field with
*
wildcard or the domain that you want to use for redirects. - Valid post logout redirect URIs field with
*
wildcard or the domain that you want to use for logout redirects. - Web origins field with
*
wildcard to allow all origins.
- Valid redirect URIs field with
- Scroll down to the Capability config section and update the following sections:
- Toggle the Client authentication setting to
Off
to enable public access. - In the Authentication flow section, enable the Standard Flow Enabled and Direct access grants options.
- Toggle the Client authentication setting to
- At the bottom of the form, click Save. The
Client successfully updated
message pops up to confirm your settings are saved. - From the client Advanced tab, find the Advanced settings. Set the Proof Key for Code Exchange Code Challenge Method dropdown to
S256
. For more information on PKCE, refer to RFC 7636. - Scroll down and click Save. The
Client successfully updated
message pops up to confirm your settings are saved.
- For developer portal: Get the OIDC endpoint details.
- From the sidebar menu options, click Realm Settings.
- From the General tab, scroll down to the Endpoints section and open the OpenID Endpoint Configuration link. In a new tab, your browser opens to a URL similar to
http://$KEYCLOAK_URL:8080/realms/master/.well-known/openid-configuration
- In the OpenID configuration, search for the
token_endpoint
field. Save the value as an environment variable, such as the following example.export TOKEN_ENDPOINT=$KEYCLOAK_URL/realms/master/protocol/openid-connect/token
- In the OpenID configuration, search for the
authorization_endpoint
field. Save the value as an environment variable, such as the following example.export AUTH_ENDPOINT=$KEYCLOAK_URL/realms/master/protocol/openid-connect/auth
- In the OpenID configuration, search for the
end_session_endpoint
field. Save the value as an environment variable, such as the following example.export LOGOUT_ENDPOINT=$KEYCLOAK_URL/realms/master/protocol/openid-connect/logout
Step 3: Create an OAuth policy
Create the resources needed to enforce an OAuth policy that uses Keycloak as the OIDC provider.
Create an AuthConfig resource with your external authentication rules. The following example sets up access token validation. To validate access tokens, you configure the Gloo Gateway external auth server to use the Keycloak JWKS server at the address that you previously got when you configured Keycloak. For more options, see the OAuth2 API docs.
kubectl apply -f - <<EOF apiVersion: enterprise.gloo.solo.io/v1 kind: AuthConfig metadata: name: oauth-keycloak namespace: httpbin spec: configs: - oauth2: accessTokenValidation: jwt: remoteJwks: url: "${KEYCLOAK_JWKS_URI}" EOF
Create a RouteOption resource that refers to the AuthConfig resource that you just created.
kubectl apply -f- <<EOF apiVersion: gateway.solo.io/v1 kind: RouteOption metadata: name: httpbin-oauth namespace: httpbin spec: options: extauth: configRef: name: oauth-keycloak namespace: httpbin EOF
Create an HTTPRoute resource for the httpbin app that requires authentication with Keycloak for requests along the
/status/200
path. If the request does not include a valid token, the request is denied with a403 Forbidden
HTTP status code.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: httpbin-oauth-keycloak namespace: httpbin spec: hostnames: - "www.httpbin.org" parentRefs: - name: http namespace: gloo-system rules: - matches: - path: type: Exact value: /status/200 filters: - type: ExtensionRef extensionRef: group: gateway.solo.io kind: RouteOption name: httpbin-oauth backendRefs: - name: httpbin port: 8000 EOF
Step 4: Verify the OAuth policy
Verify that your resources are in an
Accepted
state. If not, review the messages. Common issues include referencing the wrong RouteOption resource in theextensionRef
filter, creating multiple RouteOption resources and attaching them via thetargetRefs
option, or missing ReferenceGrants for resources that are in different namespaces.kubectl describe AuthConfig -n httpbin oauth-keycloak kubectl describe RouteOption -n httpbin httpbin-oauth kubectl describe HttpRoute -n httpbin httpbin-oauth-keycloak
Send a request to the protected httpbin route. Verify that you get back a
403
error status code.curl -i http://$INGRESS_GW_ADDRESS:8080/status/200 -H "host: www.httpbin.org:8080"
Example output:
HTTP/1.1 403 Forbidden
Generate a token for
user1
in your Keycloak OIDC provider. If you get a404
response, verify that the Keycloak URL for the OIDC token is correct. Common errors include using a different realm.export USER1_TOKEN=$(curl -Ssm 10 --fail-with-body \ -d "client_id=${KEYCLOAK_CLIENT}" \ -d "client_secret=${KEYCLOAK_SECRET}" \ -d "username=user1" \ -d "password=password" \ -d "grant_type=password" \ "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token)
Repeat the request. This time, include the token that you just created as part of the authorization header. Verify that you get back a
200
success status code.curl -i http://$INGRESS_GW_ADDRESS:8080/status/200 -H "host: www.httpbin.org:8080" -H "Authorization: Bearer $USER1_TOKEN"
Example output:
HTTP/1.1 200 OK
Cleanup
You can optionally remove the resources that you set up as part of this guide.Remove Keycloak from your cluster.
kubectl delete namespace keycloak
Delete the resources that you created for the external auth policy.
kubectl delete AuthConfig -n httpbin oauth-keycloak kubectl delete RouteOption -n httpbin httpbin-oauth kubectl delete HttpRoute -n httpbin httpbin-oauth-keycloak