Hi,
I am trying to setup Postgrest to use JWT's authenticating via Keycloak but am struggling with where I put the client secret.
If I use jwt.io and select RS256 then enter my public keycloak cert and my private key I can verify tokens that have been generated by keycloak, including checking they have the correct roles for postgrest.
What I am unsure of is how do i convert the public key certificate and client secret I have from there (which work with jwt.io) to be a client_secret in postgrest.
I have managed to generate a JWT with just the public cert in the following format:
{"alg":"RS256","e":"AQAB","kid":"lK2dtP5SJCAzhrYjBBE7VecNsCbK59LiOYF5ch-Pmuo","kty":"RSA","n":"xxxxx","use":"sig"}
I note that is has "use" and not "key_ops" - it does not seem to make any difference if i manually add that. But it does not include the secret and thus postgrest fails and calls with 401 {"message":"JWSError JWSInvalidSignature"}
Thanks
Mark
Hm.. did you escaped the quotes on the jwt-secret like {\"alg\": .. }? Check http://postgrest.org/en/v5.1/auth.html#asym-keys
Also you could try specifying the jwt-secret as a file, like jwt-secret = "@rsa.jwk.pub".
@pixie79 Did you managed to solve this?
Hi Steve,
Yes I did following advise from Russel.
In postgrest.conf add the JWK (making sure you escape it), e.g:
jwt-secret = "{ \"kty\": \"RSA\", \"n\": \"5bakJ-pSt99z3RcdGWi0Xmb6F8hIjDSWU5xCTC0bQ1F-KQ9yusTz-nevkzp6MnuRiO2P9-_vqbpdh6XXbWh94KJdFk8SCP3DocCDx0rY3b4bhK-KuF9CM5jA1XeNxekeZYjrynmGCTFUD6ewGlXupNUke_LcKMhQVzxFsOmAAGmM0604hoBpxXmwhf-594MtpGwDRgKf_4y15leSmW-_B7UImH3jED9WZkiBZM2y2jdbrfb9XsKb2xzPPoqWNTE9XMewmesQCi0CyMNBxyJyuUxNbQmcLQUNUZ_CNWZcaRqAGfFBkuWBb_G51dBZrU4Qtcb4ZRkTSoRbEWUbfrh_8w\", \"e\": \"AQAB\" }"
Create a client with public access type. Add the name to postgrest.conf, e.g: jwt-aud = "myClient"
Create a client mapper for the postgrest role (remember the JWT your client sends postgrest must have a "role" key otherwise it switches to anonymous mode). For testing you can create a hardcoded claim and later switch to using a user attribute or something. So if you create a hardcoded claim of "admin" then make sure that there is a corresponding PostgreSQL user called that which has access to what you're requesting.
For testing can get a JWT like so:
curl -s -d "client_id=myClient" -d "username=user" -d "password=pass" -d "grant_type=password" "$KEYCLOAK_SERVER/auth/realms/myRealm/protocol/openid-connect/token"
(be sure to replace values with a valid realm user). The JWT will be in the "access_token" key which you can use in your Authorization header of the request to postgrest. But it only lasts for 5 minutes so be quick or increase the expiry time.
Mark
I should note to get the key, I take the RS256 key from 'Realm Settings -> Master -> Keys -> active' selecting the RS256 Certificate key. This I then put into a file wrapping with the lines -----BEGIN CERTIFICATE----- / -----END CERTIFICATE-----.
After that I then run 'openssl x509 -in cert.pem -pubkey -noout' to generate the key in the correct format.
I want to add another comment here. I am using keycloak-angular and had big trouble getting this to work. All the steps in here are correct, but Angular sends Authorization: bearer instead of Authorization: Bearer by default. This can be fixed by using keycloak.init({bearerPrefix: 'Bearer'}) in your initializer for the library. Took my ages to figure out.
Here is an example one liner that get the key in the correct format.
curl https://KEYCLOAK_URL/auth/realms/REALM_NAME/protocol/openid-connect/certs | jq -rc '.keys | first | {kid, kty, alg, n, e}'
Most helpful comment
I should note to get the key, I take the RS256 key from 'Realm Settings -> Master -> Keys -> active' selecting the RS256 Certificate key. This I then put into a file wrapping with the lines -----BEGIN CERTIFICATE----- / -----END CERTIFICATE-----.
After that I then run 'openssl x509 -in cert.pem -pubkey -noout' to generate the key in the correct format.