keycloak

Brute force protection in keycloak


I am trying to implement brute force protection in keycloak. I am able to implement it via the admin console. However, I am not able to find where keycloak stores details of temporariliy locked users in keycoak. I am using keycloak 21.0.0. Any idea on the tables where the data of brute force is stored at keycloak's end will be immensely helpful. Thanks in advance.


Solution

  • Permanent Lock Information

    Permanent Lock Information is USER_ATTRIBUTE table at VALUE column

    MariaDB [keycloak]> SELECT * FROM USER_ATTRIBUTE;
    +----------------+------------------+--------------------------------------+--------------------------------------+
    | NAME           | VALUE            | USER_ID                              | ID                                   |
    +----------------+------------------+--------------------------------------+--------------------------------------+
    | disabledReason | permanentLockout | a0cbe53b-26b2-4bd1-981a-0abac0a72483 | 8ac10d9d-ab07-4a02-9f31-b647b7ecff48 |
    +----------------+------------------+--------------------------------------+--------------------------------------+
    

    enter image description here

    UI Setting for Permanent Lock in Keycloak (*Figure 2) enter image description here

    enter image description here

    user_temporarily_disabled

    The user_temporarily_disabled is in EVENT_ENTITY Table at ERROR column

    Simple EVENT_ENTITY Table (just 3 columns)

    -+---------------------------+----------------+------------------------------
     | ERROR                     |  TYPE          | USER_ID
    -+---------------------------+----------------+------------------------------
     | NULL                      |  LOGOUT        | c3fecc20-5fb3-4a02-be85-988b5
     | NULL                      |  LOGOUT        | 013cb4da-bb6f-487a-ba3b-a60fe
     | NULL                      |  CODE_TO_TOKEN | 013cb4da-bb6f-487a-ba3b-a60fe
     | invalid_user_credentials  |  LOGIN_ERROR   | 013cb4da-bb6f-487a-ba3b-a60fe
     | user_temporarily_disabled |  LOGIN_ERROR   | 013cb4da-bb6f-487a-ba3b-a60fe
     | NULL                      |  LOGIN         | 013cb4da-bb6f-487a-ba3b-a60fe
     | invalid_user_credentials  |  LOGIN_ERROR   | 013cb4da-bb6f-487a-ba3b-a60fe
     | invalid_user_credentials  |  LOGIN_ERROR   | 013cb4da-bb6f-487a-ba3b-a60fe
    -+---------------------------+----------------+------------------------------
    

    Full EVENT_ENTITY Table

    MariaDB [keycloak]> SELECT * FROM EVENT_ENTITY;
    +--------------------------------------+-----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------+------------+--------------------------------------+--------------------------------------+---------------+---------------+------------------------------
    --------+
    | ID                                   | CLIENT_ID       | DETAILS_JSON                                                                                                                                                                                                                                                                                        | ERROR                     | IP_ADDRESS | REALM_ID                             | SESSION_ID                           | EVENT_TIME    | TYPE          | USER_ID
            |
    +--------------------------------------+-----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------+------------+--------------------------------------+--------------------------------------+---------------+---------------+------------------------------
    --------+
    | 079a5ca0-9ed2-41c1-81ad-c381bf2baa5a | NULL            | {"redirect_uri":"http://localhost:8080/realms/master/account/#/"}                                                                                                                                                                                                                                   | NULL                      | 172.22.0.1 | 5f9b5416-259d-4c38-b27b-afb5d6200789 | ad2493fc-24c4-4299-834c-56878f0758af | 1691711078287 | LOGOUT        | c3fecc20-5fb3-4a02-be85-988b5
    c686467 |
    | 693e86d1-b749-4b77-8d90-8650b26853df | NULL            | {"redirect_uri":"http://localhost:8080/realms/master/account/"}                                                                                                                                                                                                                                     | NULL                      | 172.22.0.1 | 5f9b5416-259d-4c38-b27b-afb5d6200789 | b17cebed-0726-4092-ac73-531accf2da50 | 1691711091836 | LOGOUT        | 013cb4da-bb6f-487a-ba3b-a60fe
    8898ea6 |
    | 8b94431c-f7dc-415d-8c84-7ce3d654efc8 | account-console | {"token_id":"4e687bef-af48-4703-a3c2-07ad76f69b17","grant_type":"authorization_code","refresh_token_type":"Refresh","scope":"openid profile email","refresh_token_id":"7bf6871f-48dc-4e7b-8e9a-86027b70d261","code_id":"b17cebed-0726-4092-ac73-531accf2da50","client_auth_method":"client-secret"} | NULL                      | 172.22.0.1 | 5f9b5416-259d-4c38-b27b-afb5d6200789 | b17cebed-0726-4092-ac73-531accf2da50 | 1691711088224 | CODE_TO_TOKEN | 013cb4da-bb6f-487a-ba3b-a60fe
    8898ea6 |
    | 8dc34bfd-df10-46c1-8236-e0dc7ab513d1 | account-console | {"auth_method":"openid-connect","auth_type":"code","redirect_uri":"http://localhost:8080/realms/master/account/#/security/signingin","code_id":"9bbb5166-bffb-4ebe-b743-918ee1d1aea6","username":"user2"}                                                                                           | invalid_user_credentials  | 172.22.0.1 | 5f9b5416-259d-4c38-b27b-afb5d6200789 | NULL                                 | 1691711106048 | LOGIN_ERROR   | 013cb4da-bb6f-487a-ba3b-a60fe
    8898ea6 |
    | a42f9d00-2d86-4f8b-8ba5-75e6f6e91501 | account-console | {"auth_method":"openid-connect","auth_type":"code","redirect_uri":"http://localhost:8080/realms/master/account/#/security/signingin","code_id":"9bbb5166-bffb-4ebe-b743-918ee1d1aea6","username":"user2"}                                                                                           | user_temporarily_disabled | 172.22.0.1 | 5f9b5416-259d-4c38-b27b-afb5d6200789 | NULL                                 | 1691711108318 | LOGIN_ERROR   | 013cb4da-bb6f-487a-ba3b-a60fe
    8898ea6 |
    | ab50a625-9252-4de0-8d0b-825636a7afa0 | account-console | {"auth_method":"openid-connect","auth_type":"code","redirect_uri":"http://localhost:8080/realms/master/account/#/security/signingin","consent":"no_consent_required","code_id":"b17cebed-0726-4092-ac73-531accf2da50","username":"user2"}                                                           | NULL                      | 172.22.0.1 | 5f9b5416-259d-4c38-b27b-afb5d6200789 | b17cebed-0726-4092-ac73-531accf2da50 | 1691711086823 | LOGIN         | 013cb4da-bb6f-487a-ba3b-a60fe
    8898ea6 |
    | ad370ce8-77cf-435d-b718-2d773ca1c5f8 | account-console | {"auth_method":"openid-connect","auth_type":"code","redirect_uri":"http://localhost:8080/realms/master/account/#/security/signingin","code_id":"9bbb5166-bffb-4ebe-b743-918ee1d1aea6","username":"user2"}                                                                                           | invalid_user_credentials  | 172.22.0.1 | 5f9b5416-259d-4c38-b27b-afb5d6200789 | NULL                                 | 1691711100798 | LOGIN_ERROR   | 013cb4da-bb6f-487a-ba3b-a60fe
    8898ea6 |
    | bc74260c-ad1b-49f5-b2dd-7b13723eba25 | account-console | {"auth_method":"openid-connect","auth_type":"code","redirect_uri":"http://localhost:8080/realms/master/account/#/security/signingin","code_id":"9bbb5166-bffb-4ebe-b743-918ee1d1aea6","username":"user2"}                                                                                           | invalid_user_credentials  | 172.22.0.1 | 5f9b5416-259d-4c38-b27b-afb5d6200789 | NULL                                 | 1691711103367 | LOGIN_ERROR   | 013cb4da-bb6f-487a-ba3b-a60fe
    8898ea6 |
    +--------------------------------------+-----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------+------------+--------------------------------------+--------------------------------------+---------------+---------------+------------------------------
    --------+
    

    The user_temporarily_disabled is in EVENT_ENTITY Table at ERROR column

    enter image description here

    UI Event Logs for user2 login failed enter image description here

    UI Setting for user_temporarily_disabled of Brute force detection (*Figure 3) enter image description here

    Demo docker-compose.yml

    For Keycloak V21.0.0 and mariadb V10

    services:
      mysql:
        image: docker.io/mariadb:10
        container_name: my_mysql
        environment:
          MARIADB_DATABASE: keycloak
          MARIADB_ROOT_PASSWORD: password
          MARIADB_PASSWORD: password
          MARIADB_USER: keycloak
    
      keycloak:
        image: quay.io/keycloak/keycloak:21.0.0
        container_name: my_keycloak
        environment:
          KC_HOSTNAME: localhost
          KC_HOSTNAME_PORT: 8080
          KC_HOSTNAME_STRICT_BACKCHANNEL: "true"
          KC_DB: mariadb
          KC_DB_URL: jdbc:mariadb://mysql:3306/keycloak?characterEncoding=UTF-8
          KC_DB_USERNAME: keycloak
          KC_DB_PASSWORD: password
          KEYCLOAK_ADMIN: admin
          KEYCLOAK_ADMIN_PASSWORD: admin
          KC_HEALTH_ENABLED: "true"
          KC_LOG_LEVEL: info
        healthcheck:
          test: [ "CMD", "curl", "-f", "http://localhost:8080/health/ready" ]
          interval: 15s
          timeout: 2s
          retries: 15
        command: start-dev
        ports:
          - 8080:8080
        depends_on:
          - mysql
    

    Run it

    docker compose up
    

    Access mySQL Database to see tables and contents

    docker exec -it my_mysql mysql -u root -p keycloak
    
    or (if use Windows git bash shell)
    
    winpty docker exec -it my_mysql mysql -u root -p keycloak
    

    You needs to enter password (password is password)

    password
    

    enter image description here

    Connect keycloak database

    connect keycloak;
    

    enter image description here

    Show tables

    show tables;
    

    enter image description here

    User Event monitoring setup

    enter image description here

    Permanent Lock

    Setting UI for Permanent Lock (upper image - Figure 2)

    Select Impersonate for user1 failed 3 times

    Failed login

    Setting UI for user_temporarily_disabled (upper image - Figure 3)

    Select Impersonate for user2 failed 3 times

    enter image description here

    enter image description here

    Show the USER_ENTITY table for Getting User list

    SELECT * FROM USER_ENTITY;
    

    enter image description here

    Show the USER_ATTRIBUTE table

    SELECT * FROM USER_ATTRIBUTE;
    

    enter image description here

    Show the EVENT_ENTITY table

    SELECT * EVENT_ENTITY;
    

    Result is already posted in upper.