0

I successfully receive an access token from the following call on keycloak:

http://localhost/auth/realms/myrealm/protocol/openid-connect/token

using
clent_id=myclient
grant_type=password
username=someone
password=mypasswd
client_secret=1a5debfc-63c8-48e8-95cb-b42aa0187310

I can use the token I get from this call on jwt.io, and it verifies correctly with the client secret. However, the following code always gives me an invalid signature error using the same info:

const token = "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJhOWY4NDhhYi05ZTllLTQ0ZDAtYWQ5NC1jN2VhMTBhMDMzOTIifQ.eyJleHAiOjE2Mzg1MDUwOTcsImlhdCI6MTYzODUwNDc5NywianRpIjoiMzYyZmJjNTgtMjM1Mi00YmM4LWE0NmUtMDliMGYzOTgzYzBhIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MC9hdXRoL3JlYWxtcy9teXJlYWxtIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjhlMTM1NTZlLTc2M2MtNGQxOC05OGFlLWY0ZWQ1YWFjODFiZSIsInR5cCI6IkJlYXJlciIsImF6cCI6Im15Y2xpZW50Iiwic2Vzc2lvbl9zdGF0ZSI6ImYzMWUxM2NiLWUyZDgtNGIxZC04MTQzLTgxMmU3YmE0NTQ5NiIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1teXJlYWxtIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsInNpZCI6ImYzMWUxM2NiLWUyZDgtNGIxZC04MTQzLTgxMmU3YmE0NTQ5NiIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoiTWlrZSIsInByZWZlcnJlZF91c2VybmFtZSI6InNvbWVvbmUiLCJnaXZlbl9uYW1lIjoiTWlrZSIsImVtYWlsIjoic29tZW9uZUBzb21lZmFrZWRvbWFpbi5jb20ifQ.Ir2qhdGqJzbJPn8S9TzDP2RRmN207pc8y3UrD7cCD5Q";

const secret = "1a5debfc-63c8-48e8-95cb-b42aa0187310";
jsonwebtoken.verify(token, secret, { "algorithms": ["HS256"] });

What am I missing?

Mike
  • 609
  • 12
  • 36
  • 3
    The client-secret is not the key to verify a token! You made a common mistake in using jwt.io and believe it verified the signature, but the result is wrong. Please read [here](https://stackoverflow.com/questions/69862105/jwt-io-says-signature-verified-even-when-key-is-not-provided) how to do it the right way, and you'll find out that you actually can't verify with the given secret. As the client you're not supposed to verify the token and the secret that is used to sign is really a secret of the token issuer. – jps Dec 03 '21 at 07:04
  • Thanks, I saw there was a way to get the secret on keycloak with a query. I guess the only real best practice way to verify the token is to use keycloak's rest API? – Mike Dec 03 '21 at 12:25
  • Don't post any secret on StackOverflow. I hope that one in your sample code is fake. – Ricky Mo Dec 16 '21 at 03:01

1 Answers1

0

I've just been through this myself recently using the jsonwebtoken npm package in a NestJS application. The following solved the problem:

  1. Check the answer here -> https://stackoverflow.com/a/64484150 - this explains where to get the actual client secret, because it is not shown in the Keycloak interface anywhere, the secret can only be retrieved from the Keycloak database via that SQL command

  2. Once you have that you need to change your verify call to be this:

    jsonwebtoken.verify(token, Buffer.from(secret, 'base64'), { "algorithms": ["HS256"] });

This is needed because the client secret from the database is base64 encoded.

I used this approach to reduce calls to the Keycloak server's /auth/realms/{{realm-id}}/protocol/openid-connect/userinfo endpoint which adds network overhead, but as mentioned in your comment Mike, that REST API is a valid approach.

Dominik
  • 1,366
  • 2
  • 18
  • 37