Keycloak, administration REST

Prérequis

Démarrer Keycloak (testé avec la version 12)

docker run --publish 8888:8080 \
           --env KEYCLOAK_USER=admin --env KEYCLOAK_PASSWORD=admin \
           --name kc-example --rm \
           --detach jboss/keycloak:12.0.4

Initialisation

Initialisation d’un Realm avec un Client et un User.

base_url=http://localhost:8888

# Authenticate and get token
token=$(curl -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" \
             "$base_url/auth/realms/master/protocol/openid-connect/token" \
          | jq -r .access_token)

# Create realm
curl -H "Authorization: bearer $token" -H "Content-Type: application/json" \
     -d "{\"realm\":\"example-realm\", \"enabled\":true}" \
     $base_url/auth/admin/realms

# Create client with secret
curl -H "Authorization: bearer $token" -H "Content-Type: application/json"  \
     -d "{\"clientId\":\"example-client\", \"enabled\":true, \"standardFlowEnabled\":true,  \
          \"directAccessGrantsEnabled\":true, \"rootUrl\":\"http://localhost:8181\",  \
          \"redirectUris\":[\"http://localhost:8181/*\"], \"secret\":\"example-secret\"}"  \
     $base_url/auth/admin/realms/example-realm/clients

# Create user with password
curl -H "Authorization: bearer $token" -H "Content-Type: application/json"  \
-d "{\"username\":\"swuser\", \"enabled\":true,  \
     \"credentials\": [{\"type\":\"password\",\"value\":\"swpwd\",\"temporary\":\"false\"}]}"  \
     $base_url/auth/admin/realms/example-realm/users

X.509 direct flow

Configuration du direct flow (utilisé depuis postman) pour authentification par un certificat X.509.

Attention, il y a des prérequis sur les certificats et sur le démarrage de keycloak.

# base_url et token sont initialisé comme ci-dessus

# X509 direct flow
curl --silent --header "Authorization: bearer $token" --header "Content-Type: application/json" \
     --data "{\"alias\":\"x509 direct grant\", \"providerId\": \"basic-flow\", \"topLevel\": true, \
          \"authenticationExecutions\": [{ \
               \"authenticator\": \"direct-grant-auth-x509-username\", \
               \"requirement\": \"REQUIRED\", \
               \"priority\": 0, \
               \"userSetupAllowed\": false, \
               \"autheticatorFlow\": false \
               }]}" \
     $base_url/auth/admin/realms/example-realm/authentication/flows

curl --silent --header "Authorization: bearer $token" --header "Content-Type: application/json" \
      --data "{\"provider\":\"direct-grant-auth-x509-username\"}" \
     $base_url/auth/admin/realms/example-realm/authentication/flows/x509%20direct%20grant/executions/execution

curl -X PUT --silent --header "Authorization: bearer $token" --header "Content-Type: application/json" \
     --data "{\"directGrantFlow\": \"x509 direct grant\"}" \
     $base_url/auth/admin/realms/example-realm

execution_id=$(curl --silent --header "Authorization: bearer $token" --header "Content-Type: application/json" \
                    $base_url/auth/admin/realms/example-realm/authentication/flows/x509%20direct%20grant/executions \
               | jq -r .[0].id)

...

SubjectDN

L’attribut CN du SubjectDN sert de username.

...

curl --silent --header "Authorization: bearer $token" --header "Content-Type: application/json" \
     --data "{\"config\": {\"x509-cert-auth.mapping-source-selection\": \"Subject's Common Name\", \
                           \"x509-cert-auth.canonical-dn-enabled\": \"true\", \
                           \"x509-cert-auth.user-attribute-name\": \"usercertificate\", \
                           \"x509-cert-auth.confirmation-page-disallowed\": \"true\"}, \
                           \"alias\":\"X509\"}" \
     $base_url/auth/admin/realms/example-realm/authentication/executions/$execution_id/config

Serial et IssuerDN

Dans cet exemple, la correspondance entre le certificat et l’utilisateur est faite par le n° de série et le DN de l’émetteur.

...

curl --silent --header "Authorization: bearer $token" --header "Content-Type: application/json" \
     --data "{\"config\": {\"x509-cert-auth.mapping-source-selection\":\"Certificate Serial Number and IssuerDN\", \
                           \"x509-cert-auth.mapper-selection\":\"Custom Attribute Mapper\",
                           \"x509-cert-auth.mapper-selection.user-attribute-name\":\"SerialNumber##IssuerDN\", \
                           \"x509-cert-auth.canonical-dn-enabled\":\"true\", \
                           \"x509-cert-auth.user-attribute-name\":\"usercertificate\", \
                           \"x509-cert-auth.confirmation-page-disallowed\":\"true\"}, \
              \"alias\":\"X509serial\"}" \
     $base_url/auth/admin/realms/example-realm/authentication/executions/$execution_id/config

Pour être trouvé, l’utilisateur doit avoir par 2 attributs personnalisés : SerialNumber et IssuerDN.

# Create user with Serial and IssuerDN
curl --silent --header "Authorization: bearer $token" --header "Content-Type: application/json"  \
     --data "{\"username\":\"swserialuser\", \"enabled\":true, \
              \"attributes\":{\"SerialNumber\":[\"2\"],\"IssuerDN\":[\"o=sewatech,cn=client-ca\"]}}"  \
     $base_url/auth/admin/realms/example-realm/users

L’IssuerDN est en minuscules parce qu’on a activé le format canonical.