Zugriffe in Quarkus absichern

Wie man Web-Apps des Java-Frameworks mit der Keycloak-Erweiterung SecuRole® absichert.

Das ultraschnelle Java-Framework Quarkus, das im Microservices-Bereich in 2020 Thorntail abgelöst hat, bietet Entwicklern eine moderne Programmierplatform. Denn es wird von Red Hat als das „Next Generation Kubernetes native Java-Framework“ bezeichnet.

Um das Programmieren in Quarkus sicher zu machen, ist es wichtig diese Webanwendung einer entsprechenden Zugriffskontrolle zu unterwerfen. Und das ist mit der Open Source-Software Keycloak möglich. Nur Keycloak alleine reicht nicht aus, um Programmierern den richtigen und alleinigen Zugriff auf ihre Bereiche in Quarkus zu geben. Unter heutigen Sicherheitsaspekten empfiehlt sich eine Trennung zwischen Authentifizierung und Autorisierung. Dazu bietet sich das Berechtigungsframework SecuRole® an, was eine Erweiterung von Keycloak darstellt.

 

Kurze Einführung in SecuRole:

  • Was ist SecuRole?
    • SecuRole ist ein innovativer Ansatz für agiles Rollenmanagement. Mit SecuRole ist es möglich die Grenzen existierender Konzepte zu überwinden. Denn durch optionale Parameter ermöglicht dieser Ansatz eine fein-granulare Zugriffssteuerung.
  • Die Zero-Trust-Methodik von SecuRole:
    • Ende-zu-Ende-Sicherheit für Autorisierungsinformationen
    • SecuRole bietet einen sicheren Prozess zum Transport von Autorisierungsinformationen über einen Nutzer und die Daten, auf die er in einer Client-Anwendung zugreifen darf. Durch Überprüfung der Signatur der autorisierenden Instanz kann dann die Client-Anwendung jede Anfrage verifizieren. Im Vergleich zum Transport der Autorisierungsinformation durch Nutzung klassischer OAuth- oder SAML2-kompatibler SSO-Systeme bietet diese Methode eine Ende-zu-Ende-Sicherheit. In einer Welt, in der Identity Provider mehr und mehr miteinander vernetzt sind, ist es wichtig einen zuverlässigen Weg zu haben, um User-Autorisierungen sicher nachzuweisen.
  • Technische Implementierung: Transport als JWT (JSON Web Token)

Giovanni Baruzzi erfand die SecuRole®-Technologie als Erweiterung von Keycloak, um insbesondere höhere Nutzerzahlen in Webanwendungen abwickeln zu können. Zudem vereinfacht sie die notwendige Provisionierung in Cloud-Umgebungen bzw. macht diese überflüssig. Und mit ihr implementiert man Optionen für eine fein-granulare Autorisierung in Anwendungen.

Nun aber zunächst zu Quarkus und Keycloak – im weiteren eine kurze Anleitung, wie man beides miteinander integriert.

Integration von Quarkus & Keycloak

 

Aufsetzen der Quarkus-Webanwendung, analog der folgenden Anweisungen (in Englisch):

Sind Quarkus und Keycloak einmal konfiguriert – sollte ein nicht eingeloggter Nutzer auf eine durch Keycloak geschützte Quarkus-Seite zugreifen wollen, dann wird Keycloak den Nutzer zu seiner Login-Seite umleiten:

Standard-Login-Seite von Keycloak

Quarkus und Keycloak sind ready? Nun auf zur Integration von SecuRole!

SecuRole generieren

Wie oben beschrieben, ist SecuRole ein signiertes JWT, welches viele Informationen enthält. Um Zugriff zu einer Ressource zu erhalten, ist es möglich die Annotation @RoleAllowed einzusetzen oder die Eigenschaft quarkus.security.jaxrs.default-roles-allowed festzulegen. Beides benötigt den Namen der Rolle.

Quarkus bietet eine flexible Methode, um die Identitätssicherheit (SecurityIdentity) anzupassen. Mit einem SecurityIdentityAugmentor können wir neue Informationen hinzufügen – daher auch SecuRole.

Das Attribut in Keycloak zuordnen

Nehmen wir an, dass Keycloak SecuRole als Attribut eines Nutzers speichert.

SecuRole als Nutzerattribut “userRoles” in Keycloak gespeichert

Keycloak stellt die Option bereit, Nutzerinformationen zu den Client-Anwendungen zu transportieren. Das funktioniert mit Mappern, die die Information zum Zugriffstoken hinzufügen. Das kann zum ID-Token sein oder zu den vom UserInfo-Endpunkt abrufbaren Informationen.

Aufgrund der Art, wie es aufgebaut ist, kann SecuRole sehr groß werden. Schon ein kleiner Satz an Rollen kann problematisch sein, da Keycloak die Token technisch in Cookies (keine Sitzungscookies!) speichert. Diese haben eine begrenzte Größe von 4KB. Um daher Datenverluste oder Fehler zu vermeiden, ist es besser SecuRole nur über den UserInfo-Endpunkt zu vermitteln. In unserem Fall wird Quarkus es automatisch aufrufen. Und Quarkus speichert die Daten in einem Objekt, das sich in einen SecurityIdentityAugmentor einführen lässt.

Dazu definiert man für den Client einen Mapper, den man für die Nutzerauthentifizierung einsetzt:

Konfigurationsseite eines OIDC-Mappers

Durch Hinzufügen des folgenden Abschnitts, kann man die Konfiguration der Anwendung wie folgt modifizieren:

quarkus:

oidc:

authentication:

user-info-required: true

Nun wird Quarkus automatisch das Attribut „userinfo“ des Objektes SecurityIdentity füllen durch Aufruf des entsprechenden Endpunktes. Und Keycloak wird den Inhalt des userRole-Attributes liefern. An diesem Punkt sind die Rollennamen nicht direkt zugänglich, da der Mapper SecuRole wie folgt darstellt: eine Liste von „##“-getrennten Strings:

loginalliance:MUSCA:MUSCA_ACCESS:eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI5NTczNjUwMzE0NjQ1OTciLCJhdWQiOiJNVVNDQSIsInZlciI6IjEuMC4wIiwibmJmIjoxNjI0NjE0NjU1LCJpc3MiOiJpbnRlbnNpb24gZ21iaCIsInJsZSI6Ik1VU0NBX0FDQ0VTUyIsInBybSI6IlRoaXMgcm9sZSBpcyBib3VuZCB0byB0aGUgZW52aXJvbm1lbnQgb2YgaW50ZW5zaW9uIGdtYmgiLCJleHAiOjQ3ODM4NDAyODcsImlhdCI6MTYyNDYxNDY1NSwianRpIjoiNyJ9.EkjuC5ZALxOb8Z-dwCpsmxq7ieMS3bg48BukVG-qJ3qWVvr6F8yMbiKa5T3yHujmyuzzMuJulf7pcY8x4mnBmxvxeA_74GbZ-FEkVN7R3-T7po4Ubl9xMtzWhVQgWoqKv2IsAs3Y2OXtwM7v1E5gOqBH5ExAcZNr3xfczasL8u2GnzPHcYbNkKztxId8cizXPWykKGAwz-STvCCTmSeXlOBK14-V3Zr2kQmqw_cVJsiIS2tBtyHB1oNzddLEj4qpFMMES–v1AFISl8w6pcG-ZuBbXKI0SOrhHebYhQ2Ep-HBtol6zf3a8J9qFNcbtsFkUmSqg86gfYBQ9UzeK9_sw##loginalliance:DEMO:APPLICATION_ACCESS:eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI5NTczNjUwMzE0NjQ1OTciLCJhdWQiOiJERU1PIiwidmVyIjoiMS4wLjAiLCJuYmYiOjE2MjQ2MTQ3MDksImlzcyI6ImludGVuc2lvbiBnbWJoIiwicmxlIjoiQVBQTElDQVRJT05fQUNDRVNTIiwicHJtIjoiVGhpcyByb2xlIGlzIGJvdW5kIHRvIHRoZSBlbnZpcm9ubWVudCBvZiBpbnRlbnNpb24gZ21iaCIsImV4cCI6NDc4Mzg0MDI4NywiaWF0IjoxNjI0NjE0NzEzLCJqdGkiOiI5In0.XE0Zp-iSuFhgQZ3Z4wOCg9VPdNtBqfFlimKmr5bS4_orRHDYCdVNaHYpTGzYgjejN8Ad6kM67MziH-PuNckzrv8mKqEFsfy2jq_mW508VYW8iDIkY6BaJ5_kir3E7_DkeUNDs3YUr2w5RWo-bLlr6C0N0tEcPjiWtAi2xn_D6U2mnXlFnMNvuD-fGbfmtlC08zWQOHX_wMkR-WcnSUrtY5gBxcNgzkWVtIVNi1ue9VMfSWbUtoeKL8RKdc0bkGVoGYutA59nLmbr9qyOwjytyW1HVcujwVzBsKrGtVzwHyi142iZTBt765_Gy1V-xEksrZot-CEymD9BCURJPG6UEw##loginalliance:MyProfile:LOGIN:eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI5NTczNjUwMzE0NjQ1OTciLCJhdWQiOiJNeVByb2ZpbGUiLCJ2ZXIiOiIxLjAuMCIsIm5iZiI6MTYyNDYxNDY1NSwiaXNzIjoiaW50ZW5zaW9uIGdtYmgiLCJybGUiOiJMT0dJTiIsInBybSI6IlRoaXMgcm9sZSBpcyBib3VuZCB0byB0aGUgZW52aXJvbm1lbnQgb2YgaW50ZW5zaW9uIGdtYmgiLCJleHAiOjQ3ODM4NDAyODcsImlhdCI6MTYyNDYxNDY1NSwianRpIjoiOCJ9.D5CN-i2EFeZshl8d8oMLFK80-M9jzDPM-qHvjyqtLBlLEmCRyNgJumj-99eExE1ifF9wH2GgHu7FC_QJ6A2Ma1XtZd1eqIJ0-BY6mxylHYBfMHHgA–B58SRz_MCRozNCPM2WtQhFXkCsD6LzzXmBm9GOLasYenHEz5hSRvS_QDeHsjB7Cfy-7rNGBU3enI-V4uY0rlTV8ygwWq6NzjYMzjio6WV18I7HqRbUFFKTj6rEgIBYJIRT5n87QqAOvVaZN-A8i_KSuhRbTqVkLFzUHcNYIqNseDzMTDptOHpHTbXyqQrOKX6GEQ_xkXHNe49duLZg97NfcbJ0y66ustNtw

Da ist schon manche Information in Klartext, aber in Wirklichkeit befindet sich der sichere Teil in einem JWT – hier ein Beispiel:

eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI5NTczNjUwMzE0NjQ1OTciLCJhdWQiOiJNVVNDQSIsInZlciI6IjEuMC4wIiwibmJmIjoxNjI0NjE0NjU1LCJpc3MiOiJpbnRlbnNpb24gZ21iaCIsInJsZSI6Ik1VU0NBX0FDQ0VTUyIsInBybSI6IlRoaXMgcm9sZSBpcyBib3VuZCB0byB0aGUgZW52aXJvbm1lbnQgb2YgaW50ZW5zaW9uIGdtYmgiLCJleHAiOjQ3ODM4NDAyODcsImlhdCI6MTYyNDYxNDY1NSwianRpIjoiNyJ9.EkjuC5ZALxOb8Z-dwCpsmxq7ieMS3bg48BukVG-qJ3qWVvr6F8yMbiKa5T3yHujmyuzzMuJulf7pcY8x4mnBmxvxeA_74GbZ-FEkVN7R3-T7po4Ubl9xMtzWhVQgWoqKv2IsAs3Y2OXtwM7v1E5gOqBH5ExAcZNr3xfczasL8u2GnzPHcYbNkKztxId8cizXPWykKGAwz-STvCCTmSeXlOBK14-V3Zr2kQmqw_cVJsiIS2tBtyHB1oNzddLEj4qpFMMES–v1AFISl8w6pcG-ZuBbXKI0SOrhHebYhQ2Ep-HBtol6zf3a8J9qFNcbtsFkUmSqg86gfYBQ9UzeK9_sw

 

 

  1. Der erste Teil legt den genutzten Algorithmus fest:
    eyJhbGciOiJSUzI1NiJ9
  2. {
  3. „alg“: „RS256“
    }
  4. Dann der Payload, der den Rollennamen enthält:
    eyJzdWIiOiI5NTczNjUwMzE0NjQ1OTciLCJhdWQiOiJNVVNDQSIsInZlciI6IjEuMC4wIiwibmJmIjoxNjI0NjE0NjU1LCJpc3MiOiJpbnRlbnNpb24gZ21iaCIsInJsZSI6Ik1VU0NBX0FDQ0VTUyIsInBybSI6IlRoaXMgcm9sZSBpcyBib3VuZCB0byB0aGUgZW52aXJvbm1lbnQgb2YgaW50ZW5zaW9uIGdtYmgiLCJleHAiOjQ3ODM4NDAyODcsImlhdCI6MTYyNDYxNDY1NSwianRpIjoiNyJ9
  5. {
  6. „sub“: „957365031464597“,
  7. „aud“: „MUSCA“,
  8. „ver“: „1.0.0“,
  9. „nbf“: 1624614655,
  10. „iss“: „intension gmbh“,
  11. „rle“: „MUSCA_ACCESS“,
  12. „prm“: „This role is bound to the environment of intension gmbh“,
  13. „exp“: 4783840287,
  14. „iat“: 1624614655,
  15. „jti“: „7“
  16. }

  17. Zuletzt die Signatur:
    EkjuC5ZALxOb8Z-dwCpsmxq7ieMS3bg48BukVG-qJ3qWVvr6F8yMbiKa5T3yHujmyuzzMuJulf7pcY8x4mnBmxvxeA_74GbZ-FEkVN7R3-T7po4Ubl9xMtzWhVQgWoqKv2IsAs3Y2OXtwM7v1E5gOqBH5ExAcZNr3xfczasL8u2GnzPHcYbNkKztxId8cizXPWykKGAwz-STvCCTmSeXlOBK14-V3Zr2kQmqw_cVJsiIS2tBtyHB1oNzddLEj4qpFMMES–v1AFISl8w6pcG-ZuBbXKI0SOrhHebYhQ2Ep-HBtol6zf3a8J9qFNcbtsFkUmSqg86gfYBQ9UzeK9_sw

Die Signatur checken

Jetzt ist es möglich die Rolle aus dem Payload zu extrahieren. Und die Signatur des JWT zu verifizieren, um sicher zu gehen, dass niemand diese manipuliert hat. Dazu ist es möglich die Nimbus JOSE + JWT-Library, die einen einfachen Signaturcheck gegen den angebotenen Public Key erlaubt.

Das war: „Zugriffe auf Internetanwendungen wie Quarkus sicherer machen durch Keycloak und seine Erweiterung SecuRole®.

Bei Fragen melden Sie sich gerne über unser Kontaktformular: