J'ai réalisé qu'il y avait de nombreuses itérations de ces questions. Mais je n'arrive pas à comprendre correctement la réponse.
Nous avons sécurisé nos points de terminaison rabbitmq et repos avec un serveur de printemps oauth2 similaire à ce message . Mais il ne possède pas toutes les fonctionnalités dont nous avons besoin et que nous voulons. Nous aimerions donc utiliser Keycloak. J'ai réussi à sécuriser le point de terminaison de repos en accédant simplement à la nouvelle version de Spring Security 5.1 et en spécifiant security.oauth2.resource.jwk.key-set-uri et en définissant les dépendances et la configuration nécessaires.
En essayant de sécuriser RabbitMQ, j'ai rencontré des problèmes lors de la vérification du jeton de support à partir de l'en-tête du message car le point de terminaison keycloak jwks ne renvoie pas la vraie clé publique RSA.
RabbitMQ utilise le CustomMessageListenerContainer pour obtenir le jeton de l'en-tête du message et utilise les DefaultTokenServices pour vérifier le jeton.
D'après ce que je comprends, le point de terminaison qui répond avec la clé est https: // keycloak-server / auth / realms / my-realm / protocol / openid-connect / certs En faisant un HttpGet sur ce point de terminaison, j'obtiens une réponse qui ressemble à la suivante
{ "keys": [{ "kid": "7JUbcl_96GNk2zNh4MAORuEz3YBuprXilmTXjm0gmRE", "kty": "RSA", "alg": "RS256", "use": "sig", "n": "nE9gEtzZvV_XisnAY8Hung399hwBM_eykZ9J57euboEsKra8JvDmE6w7SSrk-aTVjdNpjdzOyrFd4V7tFqev1vVJu8MJGIyQlbPv07MTsgYE5EPM4DxdQ7H6_f3vQjq0hznkFvC-hyCqUhxPTXM5NgvH86OekL2C170xnd50RLWw8FbrprP2oRjgBnXMAif1Dd8kwbKKgf5m3Ou0yTVGfsCRG1_LSj6gIEFglxNHvGz0RejoQql0rGMxcW3MzCvc-inF3FCafQTrG5eWHqp5xXEeMHz0JosQ7BcT8MVp9lHT_utiazhQ1uKZEb4uoYOyy6mDDkx-wExpZkOx76bk_Yu-N25ljY18hNllnV_8gVMkX46_vcc-eN3DRZGNJ-Asd_sZrjbXbAvBbKwVxZeOTaXiUdvl8O0G5xX2xPnS_WA_1U4b_V1t28WtnX4bqGlOejW2kkjLvNrpfQ5fnvLjkl9I2B16Mbh9nS0LJD0RR-AkBsv3rKEnMyEkW9UsfgYKLFKuH32x_CXi9uyvNDas_q8WS3QvYwAGEMRO_4uICDAqupCVb1Jcs9dvd1w-tUfj5MQOXB-srnQYf5DbFENTNM1PK390dIjdLJh4k2efCJ21I1kYw2Qr9lHI4X2peTinViaoOykykJiol6LMujUcfqaZ1qPKDy_UnpAwGg9NyFU", "e": "AQAB" } ] }
D'après ce que je comprends, le champ avec la clé "n" est censé être une clé RSA256. L'ajouter à un RSAVerifier obtient finalement une erreur de "Caused by: org.springframework.security.jwt.codec.InvalidBase64CharacterException: Bad Base64 input character decimal 95 in array position 2."
Cependant, si je me connecte à la page d'administration de keycloak et allez dans les paramètres du royaume -> clés et cliquez sur la clé publique, une fenêtre contextuelle affiche la clé publique moins les "----- BEGIN PUBLIC KEY -----" et "----- END PUBLIC KEY ----- "en-têtes et pieds de page. Le codage en dur permet à tout de fonctionner.
La clé est-elle codée? J'ai essayé de faire un Base64Utils.decodeFromUrlSafeString et un Base64Utils.decodeFromString. Le premier retourne quelque chose de plus petit et ne loule pas comme la clé et le second crée une exception d'argument illégale Caractère base64 illégal 5f.
Mise à jour: Le n renvoyé est le moduleux et e est l'exposant public de la clé publique. Mais comment obtenir la chaîne de clé réelle?
3 Réponses :
Il y a toIntegerBytes
avant l'encodage base64 , il ne s'agit donc pas seulement d'un décodage base64. Essayez:
BigInteger modulus = new BigInteger(1, Base64.decodeBase64("n-value-here")); BigInteger exponent = new BigInteger(1, Base64.decodeBase64("e-value-here"));
Les clés sont également directement sur https: // keycloak-server / auth / realms / my- royaume , dans un format directement exploitable avec votre code:
{ "realm": "my-realm", "public_key": "MIIBI...", "token-service": "https://keycloak-server/auth/realms/my-realm/protocol/openid-connect", "account-service": "https://keycloak-server/auth/realms/my-realm/account", "tokens-not-before": 0 }
Je souhaite vraiment que cela soit mieux documenté. Cela m'aurait fait gagner beaucoup de temps. Merci pour votre réponse.
Je dois aussi demander, comment avez-vous connu cette réponse? J'ai passé assez de temps à parcourir la documentation et elle ne fait référence qu'au point de terminaison jwks_uri.
@ "Thomas Lann" Je suis tombé dessus en testant, tu as raison, ce n'est pas vraiment annoncé, ce qui veut dire aussi que je ne sais pas vraiment si ça va rester ou non.
J'ai trouvé dans le code Spring oauth2 un exemple partiel de conversion du jwk en RSAVerifier. J'ai donc quelque chose qui fonctionne, mais ce n'est pas un très bon code. J'ai du mal à trouver de bons exemples d'utilisation de JWK en dehors du démarrage à ressort régulier en définissant l'URI dans une propriété. J'imagine que cela a quelque chose à voir avec la création d'un JwkTokenStore similaire à un JwtTokenStore.
Avec le point de terminaison ci-dessous, vous pouvez obtenir la liste des points de terminaison keycloak openId exposés http: // localhost: 8080 / auth / realms / {my_realm} /.well-known/ope nid-configuration
Pour obtenir ' jwks_uri 'utilise le point de terminaison ci-dessous http: // localhost: 8080 / auth / realms / {my_realm} / protocol / openid -connect / certs
Juste pour n'importe qui, qui trébucherait ici ..
Une idée comment obtenir l'expiration de la clé publique? Je suppose qu'il devrait éventuellement tourner. J'ai inspecté le certificat depuis l'interface utilisateur de keycloak où vous pouvez obtenir manuellement la clé publique, et c'était une expiration de 10 ans. Mais ce n'est pas une évidence qu'il n'est pas prévu de changer avant cela. Je m'attends à ce qu'il y ait une panne de courte durée, inexpliquée, dans quelques années. : - / Pour l'instant, je mets simplement la clé en cache pendant 15 m à la fois.
Je le trouverai également sur: