Skip to content
Snippets Groups Projects

WIP: Keycloak mail pass integration

Description

Enable Keycloak mail pass integration.

Resolves #217

TODOs

  • Modify theme to add a custom attribute "mail_password_hash" to the account management console
  • Implement a domain extension to provide custom REST endpoint for bcrypt with cost 12 and 2b variant
  • Implement an add "password-validate" REST endpoint which use the internal Keycloak API
  • Ensure the password hash attribute in Keycloak can be modified (via the templating engine)
  • Update mail credential syncer script to use 2b variant

To Verify

  • Code building and testing process (maven, gradle etc) - currently gradle is being used
  • Package naming scheme - currently org.archlinux.keycloak.mailpass.rest
  • JAR naming scheme - currently keycloak-mailpass-rest-{x.x.x}.jar
  • Endpoint naming scheme - currently using /mailpass/hashify and /mailpass/validate (not included yet)
  • Whether or not to use the same JAR for both generating hashes and validating
  • Code quality, comments, styling linting etc - currently using Google standards
  • Source placement such as which repository and which directory - currently deployment is assumed to take place via Ansible so data was placed in Keycloak role files directory under providers (similar to theme deployment)

Status Updates:

08/12/2020: A custom REST endpoint has been implemented to compute bcrypt hash for user provided passwords (no auth required)

image

15/12/2020: The custom REST endpoint for computing the password hashes has been converted to a domain extension that requires authentication for request

. ./invoke-authenticated.sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2354  100  2285  100    69  21157    638 --:--:-- --:--:-- --:--:-- 21796


SENT RESOURCE-OWNER-PASSWORD-CREDENTIALS-REQUEST. OUTPUT IS:


HTTP/1.1 200 OK
Cache-Control: no-store
Set-Cookie: KEYCLOAK_LOCALE=; Version=1; Comment=Expiring cookie; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=0; Path=/auth/realms/master/; HttpOnly
Set-Cookie: KC_RESTART=; Version=1; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=0; Path=/auth/realms/master/; HttpOnly
X-XSS-Protection: 1; mode=block
Pragma: no-cache
X-Frame-Options: SAMEORIGIN
Referrer-Policy: no-referrer
Date: Tue, 15 Dec 2020 06:52:40 GMT
Connection: keep-alive
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
Content-Type: application/json
Content-Length: 2285

{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJFYjZhV3ExSXhHbm5wMVBYSTlSUVVWRm96Tm1hWVFLSGlfX3pqb1pEclFBIn0.eyJleHAiOjE2MDgwMTUyMjAsImlhdCI6MTYwODAxNTE2MCwianRpIjoiODE1ZDBhMzMtYjJjOC00MWIwLTg4MjktMmEwODM0Y2M5ZmI4IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsImF1ZCI6Im1hc3Rlci1yZWFsbSIsInN1YiI6ImRmZDYxMWM0LTk0NDEtNGE0MC1hZjE3LTRhNTkzZjQxM2FkYyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFkbWluLWNsaSIsInNlc3Npb25fc3RhdGUiOiJmNGU1OGYzMy1kZTBkLTQ4YjgtYjBhOS1iZjY5ZDA5ZDg4ZjciLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImNyZWF0ZS1yZWFsbSIsImFkbWluIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsibWFzdGVyLXJlYWxtIjp7InJvbGVzIjpbInZpZXctaWRlbnRpdHktcHJvdmlkZXJzIiwidmlldy1yZWFsbSIsIm1hbmFnZS1pZGVudGl0eS1wcm92aWRlcnMiLCJpbXBlcnNvbmF0aW9uIiwiY3JlYXRlLWNsaWVudCIsIm1hbmFnZS11c2VycyIsInF1ZXJ5LXJlYWxtcyIsInZpZXctYXV0aG9yaXphdGlvbiIsInF1ZXJ5LWNsaWVudHMiLCJxdWVyeS11c2VycyIsIm1hbmFnZS1ldmVudHMiLCJtYW5hZ2UtcmVhbG0iLCJ2aWV3LWV2ZW50cyIsInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJtYW5hZ2UtYXV0aG9yaXphdGlvbiIsIm1hbmFnZS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiJ9.KdW29aewp8401Yuusr_cQ6bsrUFadbKzGb18-Oi0A0dQ69PqCLYCWwgCQIhBKBHIPPZ9ilWaAn7Yk5eumf_Yua0cKZfWGLG0_tDuwLjhGJCTcxXVXd42K9cKMnmox2MwuKuY_hRtvPjzBH44taeIZ8GUbF6ZNSzj792G8Fj9j5WBq-SCeVkDABC9idjkYDB4sGt-Rl5ZAdNqieuJVQ8h7KIk2eLarbHGHdo3jSRpHpaxh04g930uoU1ZXVga5GUiUetBpJLN5ud2e29JX_VuwE2SzAHojgzv6xNT9LfurpemPU0Ub0AQZDuiNYfYgBtjAfV793k5us9pmeBlOrvRkg","expires_in":60,"refresh_expires_in":1800,"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1OTRhOGM1ZS1iYTBiLTQ0ZGUtYmNhOS1kYzUyZGY2MTk0MWEifQ.eyJleHAiOjE2MDgwMTY5NjAsImlhdCI6MTYwODAxNTE2MCwianRpIjoiMWZlMGY0YjctMTVjOS00ZGZiLWI1ZDYtMTY2ZmFlZWU0ODIwIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9hdXRoL3JlYWxtcy9tYXN0ZXIiLCJzdWIiOiJkZmQ2MTFjNC05NDQxLTRhNDAtYWYxNy00YTU5M2Y0MTNhZGMiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoiYWRtaW4tY2xpIiwic2Vzc2lvbl9zdGF0ZSI6ImY0ZTU4ZjMzLWRlMGQtNDhiOC1iMGE5LWJmNjlkMDlkODhmNyIsInNjb3BlIjoiZW1haWwgcHJvZmlsZSJ9.jQD11JsimjSwVC-t3kBv6oMYBdyEguh-4UiuG3NB-vI","token_type":"bearer","not-before-policy":0,"session_state":"f4e58f33-de0d-48b8-b0a9-bf69d09d88f7","scope":"email profile"}


ACCESS TOKEN IS "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJFYjZhV3ExSXhHbm5wMVBYSTlSUVVWRm96Tm1hWVFLSGlfX3pqb1pEclFBIn0.eyJleHAiOjE2MDgwMTUyMjAsImlhdCI6MTYwODAxNTE2MCwianRpIjoiODE1ZDBhMzMtYjJjOC00MWIwLTg4MjktMmEwODM0Y2M5ZmI4IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsImF1ZCI6Im1hc3Rlci1yZWFsbSIsInN1YiI6ImRmZDYxMWM0LTk0NDEtNGE0MC1hZjE3LTRhNTkzZjQxM2FkYyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFkbWluLWNsaSIsInNlc3Npb25fc3RhdGUiOiJmNGU1OGYzMy1kZTBkLTQ4YjgtYjBhOS1iZjY5ZDA5ZDg4ZjciLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImNyZWF0ZS1yZWFsbSIsImFkbWluIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsibWFzdGVyLXJlYWxtIjp7InJvbGVzIjpbInZpZXctaWRlbnRpdHktcHJvdmlkZXJzIiwidmlldy1yZWFsbSIsIm1hbmFnZS1pZGVudGl0eS1wcm92aWRlcnMiLCJpbXBlcnNvbmF0aW9uIiwiY3JlYXRlLWNsaWVudCIsIm1hbmFnZS11c2VycyIsInF1ZXJ5LXJlYWxtcyIsInZpZXctYXV0aG9yaXphdGlvbiIsInF1ZXJ5LWNsaWVudHMiLCJxdWVyeS11c2VycyIsIm1hbmFnZS1ldmVudHMiLCJtYW5hZ2UtcmVhbG0iLCJ2aWV3LWV2ZW50cyIsInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJtYW5hZ2UtYXV0aG9yaXphdGlvbiIsIm1hbmFnZS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiJ9.KdW29aewp8401Yuusr_cQ6bsrUFadbKzGb18-Oi0A0dQ69PqCLYCWwgCQIhBKBHIPPZ9ilWaAn7Yk5eumf_Yua0cKZfWGLG0_tDuwLjhGJCTcxXVXd42K9cKMnmox2MwuKuY_hRtvPjzBH44taeIZ8GUbF6ZNSzj792G8Fj9j5WBq-SCeVkDABC9idjkYDB4sGt-Rl5ZAdNqieuJVQ8h7KIk2eLarbHGHdo3jSRpHpaxh04g930uoU1ZXVga5GUiUetBpJLN5ud2e29JX_VuwE2SzAHojgzv6xNT9LfurpemPU0Ub0AQZDuiNYfYgBtjAfV793k5us9pmeBlOrvRkg"


SENDING UN-AUTHENTICATED REQUEST. THIS SHOULD FAIL WITH 401: 
HTTP/1.1 401 Unauthorized
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Referrer-Policy: no-referrer
Date: Tue, 15 Dec 2020 06:52:40 GMT
Connection: keep-alive
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
Content-Type: application/json
Content-Length: 33

{"error":"HTTP 401 Unauthorized"}

SENDING AUTHENTICATED REQUEST. THIS SHOULD SUCCESSFULY CREATE PASSWORD HASH AND SUCCESS WITH 201: 
HTTP/1.1 201 Created
Connection: keep-alive
X-XSS-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
Content-Type: application/octet-stream
Referrer-Policy: no-referrer
Content-Length: 60
Date: Tue, 15 Dec 2020 06:52:40 GMT

$2b$12$qoWlJZiAo7C54Ud1.2of0egEk790NhhGyVoprw4gdtuCSA1/Y7gA6%      
Edited by Ira ¯\_(ツ)_/¯

Merge request reports

Loading
Loading

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
    • @jelle

      I might not fully understand how it all works but I would opt for creating a new gitlab project if this produces a jar which just has to be installed in a specific keycloak location.

      I do not mind moving the project files to a new repository but which repository should that be?

      I saw up on IRC that @klausenbusk mentioned using something like https://github.com/svenstaro/keycloak-http-webhook-provider but I am not sure how I feel about this. Having related project files under a different username does not make much sense to me. Shouldnt we make a new repository under the organization name and group all similar projects in there instead?

      My vote would be for something like archlinux/keycloak-spis or archlinux/keycloak-extensions.

      What do you guys think?

      Then we can also add proper CI/Linting and what not for Java specifics :)

      I like this idea and we should definitely do it once we decide where the project should live.

      I would also love to see some documentation describing how to build the project, use it and what it is used for.

      Is the provided README not enough? Please let me know what is missing and will be happy to add more details.

    • i agree we should move this to an own project and not make it live inside infrastructure but i also agree we should do that inside the archlinux namespace

    • Please register or sign in to reply
  • Ira ¯\_(ツ)_/¯ added 51 commits

    added 51 commits

    • 92d78b5d...7228b480 - 42 commits from branch archlinux:master
    • 689226a5 - Add Gradle build tool components
    • 23fa677c - Add configuration required to instantiate and configure Gradle project
    • 5dce9a4d - Add Gradle build script for the custom REST endpoint
    • 7fc28663 - Add .gitignore
    • efec1bfb - Add Docker files for local testing purposes
    • 8ee552cd - Add custom REST endpoint MailPassResourceProvider and factory
    • 667575a7 - Add SPI service configuration file for custom resource provider
    • d3d7879b - Add Keycloak deployer configuration file to load third-party jars
    • a9de0f7a - Add README with deployment and local testing instructions

    Compare with previous version

  • added 2 commits

    • 50b58e40 - Remove Gradle files used for isolated execution
    • 95d8b0eb - Modify .gitignore to include some files from gradle init command

    Compare with previous version

  • added 2 commits

    • a8fadac9 - Change endpoint name from "hashify" to "compute-password-hash"
    • 15de4ec3 - Update README file

    Compare with previous version

  • Ira ¯\_(ツ)_/¯ changed the description

    changed the description

  • added 2 commits

    • 9afaa656 - Convert to domain extension to enable authenticated requests
    • 32466253 - Add sample test

    Compare with previous version

  • Ira ¯\_(ツ)_/¯ added 105 commits

    added 105 commits

    • 32466253...55d7813a - 90 commits from branch archlinux:master
    • 648ee2f6 - Add Gradle build tool components
    • 44daade2 - Add configuration required to instantiate and configure Gradle project
    • f514503d - Add Gradle build script for the custom REST endpoint
    • 620224ea - Add .gitignore
    • 564249f1 - Add Docker files for local testing purposes
    • ae4eb24f - Add custom REST endpoint MailPassResourceProvider and factory
    • 02641987 - Add SPI service configuration file for custom resource provider
    • 4fa4ac5d - Add Keycloak deployer configuration file to load third-party jars
    • 13ceaa18 - Add README with deployment and local testing instructions
    • 719f93b1 - Remove Gradle files used for isolated execution
    • a0c506de - Modify .gitignore to include some files from gradle init command
    • 3d374bc5 - Change endpoint name from "hashify" to "compute-password-hash"
    • 64695d08 - Update README file
    • 54c05624 - Convert to domain extension to enable authenticated requests
    • df6a9100 - Add sample test

    Compare with previous version

  • added 7 commits

    • d4378d71 - Update project dependencies
    • 7ad68b5e - Make `password` the required object in the JSON data
    • d4bc6f49 - Formatting fixes
    • 5f811f31 - Remove sample get request and update function call to use new API
    • bae33b68 - Formatting fixes
    • 4001c52b - Add exception handling and json validation/parsing to data received
    • cb0b57ef - Update README

    Compare with previous version

  • added 4 commits

    • 2aa0c35f - Update .gitignore
    • f1baac44 - Separate unit from integration tests
    • 3f3e86e7 - Add initial integration testing setup
    • 11046fa2 - Update gradle build to enable integration testing and smoother copying

    Compare with previous version

  • Ira ¯\_(ツ)_/¯ added 33 commits

    added 33 commits

    • 11046fa2...57efb6f0 - 7 commits from branch archlinux:master
    • 1d09528d - Add Gradle build tool components
    • 53e2cd63 - Add configuration required to instantiate and configure Gradle project
    • a9bcf0f7 - Add Gradle build script for the custom REST endpoint
    • 910ea920 - Add .gitignore
    • aace5743 - Add Docker files for local testing purposes
    • 3ca3208e - Add custom REST endpoint MailPassResourceProvider and factory
    • 62525f9c - Add SPI service configuration file for custom resource provider
    • c21f325b - Add Keycloak deployer configuration file to load third-party jars
    • 58e083e4 - Add README with deployment and local testing instructions
    • a1293dda - Remove Gradle files used for isolated execution
    • 246049bd - Modify .gitignore to include some files from gradle init command
    • 4bfddc8a - Change endpoint name from "hashify" to "compute-password-hash"
    • 92f2556a - Update README file
    • 0ea367ea - Convert to domain extension to enable authenticated requests
    • 1ba51aab - Add sample test
    • f0c9a22b - Update project dependencies
    • e1601820 - Make `password` the required object in the JSON data
    • 54556dd1 - Formatting fixes
    • 5e2ae504 - Remove sample get request and update function call to use new API
    • 4d4d29e1 - Formatting fixes
    • 5a650888 - Add exception handling and json validation/parsing to data received
    • 9e556407 - Update README
    • 93ef145d - Update .gitignore
    • 9a00de7d - Separate unit from integration tests
    • a53774d5 - Add initial integration testing setup
    • 46232a75 - Update gradle build to enable integration testing and smoother copying

    Compare with previous version

  • added 4 commits

    • e05dd78d - Update build file to be gradle v7 compatible
    • 2f075ff5 - only specify internal port; move health check to JAVA; import realm conf
    • aeaa4f08 - Add master realm conf to enable admin_cli scope mappings
    • cc1a0e50 - Add health checks and token generation; add authenticated request test

    Compare with previous version

  • added 1 commit

    • 3e07f9e5 - Add exception testing and message validation

    Compare with previous version

  • Ira ¯\_(ツ)_/¯ added 48 commits

    added 48 commits

    • 3e07f9e5...32e53cac - 17 commits from branch archlinux:master
    • 409874fc - Add Gradle build tool components
    • 19c2a8b8 - Add configuration required to instantiate and configure Gradle project
    • cb3471b2 - Add Gradle build script for the custom REST endpoint
    • 83c220ae - Add .gitignore
    • d6ed9c2e - Add Docker files for local testing purposes
    • 34b41df5 - Add custom REST endpoint MailPassResourceProvider and factory
    • 12d0c0bf - Add SPI service configuration file for custom resource provider
    • a393fd95 - Add Keycloak deployer configuration file to load third-party jars
    • 7fb265de - Add README with deployment and local testing instructions
    • 42724978 - Remove Gradle files used for isolated execution
    • 97bb228f - Modify .gitignore to include some files from gradle init command
    • 68478506 - Change endpoint name from "hashify" to "compute-password-hash"
    • 7ec54ad6 - Update README file
    • 9672a797 - Convert to domain extension to enable authenticated requests
    • 965f6577 - Add sample test
    • ab1c0381 - Update project dependencies
    • 70479c91 - Make `password` the required object in the JSON data
    • eac478df - Formatting fixes
    • 1290e4f6 - Remove sample get request and update function call to use new API
    • 90739eea - Formatting fixes
    • bed622b7 - Add exception handling and json validation/parsing to data received
    • b3b892a8 - Update README
    • 4d3d6e6c - Update .gitignore
    • 75e50ea6 - Separate unit from integration tests
    • 48f0df10 - Add initial integration testing setup
    • 76430a96 - Update gradle build to enable integration testing and smoother copying
    • a2136c46 - Update build file to be gradle v7 compatible
    • b2882413 - only specify internal port; move health check to JAVA; import realm conf
    • 3d7a852a - Add master realm conf to enable admin_cli scope mappings
    • 18ceb5e4 - Add health checks and token generation; add authenticated request test
    • d659391c - Add exception testing and message validation

    Compare with previous version

  • added 1 commit

    Compare with previous version

  • added 3 commits

    • 4b21c567 - Add duplicates strategy to build file to be gradle v7 compatible
    • 1fa5ead6 - Update test environment
    • 13de9a81 - Enable realm name and role used in requests to be configured (SPI conf)

    Compare with previous version

  • Ira ¯\_(ツ)_/¯ added 76 commits

    added 76 commits

    • 13de9a81...79392cf6 - 41 commits from branch archlinux:master
    • 26c18fcf - Add Gradle build tool components
    • a78a827e - Add configuration required to instantiate and configure Gradle project
    • fbe8c714 - Add Gradle build script for the custom REST endpoint
    • 54cc3d62 - Add .gitignore
    • d03f5ec7 - Add Docker files for local testing purposes
    • 0ec0024a - Add custom REST endpoint MailPassResourceProvider and factory
    • 62d1614e - Add SPI service configuration file for custom resource provider
    • 5e1f4caf - Add Keycloak deployer configuration file to load third-party jars
    • 1a50a1e7 - Add README with deployment and local testing instructions
    • 763140c0 - Remove Gradle files used for isolated execution
    • 16ac6028 - Modify .gitignore to include some files from gradle init command
    • 05928e39 - Change endpoint name from "hashify" to "compute-password-hash"
    • 2c0ef782 - Update README file
    • 6b893ece - Convert to domain extension to enable authenticated requests
    • 247da1b7 - Add sample test
    • 218f36e7 - Update project dependencies
    • fb728ab3 - Make `password` the required object in the JSON data
    • b26c6e47 - Formatting fixes
    • 13fd896c - Remove sample get request and update function call to use new API
    • 00107dcc - Formatting fixes
    • a1c56fba - Add exception handling and json validation/parsing to data received
    • 7d07e4c4 - Update README
    • 7eacf3a2 - Update .gitignore
    • 6bcd53b3 - Separate unit from integration tests
    • c633bd55 - Add initial integration testing setup
    • fe760418 - Update gradle build to enable integration testing and smoother copying
    • 9e0ac359 - Update build file to be gradle v7 compatible
    • aabe72d5 - only specify internal port; move health check to JAVA; import realm conf
    • dd6b3cde - Add master realm conf to enable admin_cli scope mappings
    • aed24b41 - Add health checks and token generation; add authenticated request test
    • 54e2f72d - Add exception testing and message validation
    • 1e7c51aa - Fix formatting and linting
    • 5bd8f1b8 - Add duplicates strategy to build file to be gradle v7 compatible
    • c68fcf74 - Update test environment
    • efa1eaec - Enable realm name and role used in requests to be configured (SPI conf)

    Compare with previous version

  • added 3 commits

    • 8507182a - Update test environment
    • fd09db6a - Change name to be more apparent which user is being used during testing
    • 7c183609 - Expand test suite to include MailPassRestResource tests

    Compare with previous version

  • added 2 commits

    • fdd91677 - Update build to enable automatic linting, formatting and dep updating
    • 7b3a7c25 - Fix formatting and linting (google style checks)

    Compare with previous version

  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Please register or sign in to reply
    Loading