Spring Cloud Security JWT: Distribute Public Key using Config Server / Key Rotation
Asked Answered
T

2

10

How do you manage your Private / Public Keys for signing / validating JWTs in Spring Cloud environment?

The "problem":

At the moment I generate a Key Pair. Then copy Private + Public Key to my auth-server application. And also copy the Public Key to each and every Resource Server.

When I now want to implement "Key Rotation" I have to somehow populate the new keys to every service.


The idea:

Maybe I could use the spring-cloud-config-server to store and distribute the Key Pairs?

The config server already provides database login credentials. So why not store even more sensitive information there?


Question(s):

If this is the way to go: How would you implement the key pair distribution with spring-cloud-config-server?

Do you have any security concerns?

How did you solve this problem? I guess there are better solutions.


EDIT:

Maybe there's some solution using Spring Oauth's security.oauth2.resource.jwt.keyUri property for JWKs?

Topazolite answered 21/8, 2018 at 11:11 Comment(5)
Have you seen Spring Vault?Dogleg
Not yet. Thanks for the hint. Now I've been looking at it and I don't really get the difference between Vault and Config Server. I can use encryption in Config Server, too. ... My problem isn't "securing the Private / Public Keys". The problem is more like "distributing a public key to my services". My auth service should generate a new key pair every 24 hours, which it uses to sign the JWT and then it somehow needs to publish the new public key to all other services (or just publish it to config server, and all other services will retrieve it from there).Topazolite
Are you agree with the fact that if you do this, it will reject all the previously generated JWT tokens ?Lange
No, this won't work. I need to keep the current and the previous Key Pair, and then (depending on the expiration timestamp of the token) decide which Key to use to verify the JWT. If I reject every previously generated token, the client has to provide his credentials every day again and again. That's not user friendly. ... EDIT: Should be enough to keep the public key. The private key can be thrown away each rotation.Topazolite
Did my answer helped you?Hulky
H
3

You should consider the use of Spring Cloud Consul Config instead:

Consul provides a Key/Value Store for storing configuration and other metadata. Spring Cloud Consul Config is an alternative to the Config Server and Client. Configuration is loaded into the Spring Environment during the special "bootstrap" phase. Configuration is stored in the /config folder by default. Multiple PropertySource instances are created based on the application’s name and the active profiles that mimicks the Spring Cloud Config order of resolving properties.

You can POST to /refresh to update your key, or watch for changes:

The Consul Config Watch takes advantage of the ability of consul to watch a key prefix. The Config Watch makes a blocking Consul HTTP API call to determine if any relevant configuration data has changed for the current application. If there is new configuration data a Refresh Event is published.

Hulky answered 29/8, 2018 at 19:46 Comment(0)
L
2

First of all, I would had a gateway to hide the JWT mechanism. It will allow you to revoke tokens from the gateway. If an user know about his token, you can't revoke it without revoke the public key. It will look like this :

enter image description here

It's easy to implement with zuul's filters and session-scoped beans.

Secondly, has you said it in comments, you can simply create a new private key to generate new tokens. But all your resource servers must be able to read all the previously generated tokens. So you need to have a list of public key on each resource servers, and each time you receive a request, you must try to verify it with each public key. Maybe you can had a public key id (and put the id on each generated token) to avoid to do dumb look for this task.

For key distribution, use spring cloud bus and rabbit mq seems right to me.

Lange answered 25/8, 2018 at 14:39 Comment(5)
I already have a gateway, but it only does forward requests to my services. The frontend and the backend services need the information from the JWT. Of course I could use the gateway to exchange the token for a session id and then use an extra API Endpoint to retrieve the contents of the token. My revoke mechanism uses short expiration times for the access token: The client has to use his refresh token every 3 minutes and there I can deny the access / "revoke" the token. I don't need to look at all keys. I only need a Map<ExpirationTimestamp, PublicKey> to find the right key for the token.Topazolite
I currently use Spring's security.oauth2.resource.jwt.keyUri with /oauth/token_key in all my services to retrieve the current token at startup of the service. This is working fine so far. But of course it only retrieve one token once and that's it. Maybe I should just copy and modify the code of /oauth/token_key and provide a Map<ExpirationTimestamp, PublicKey>. And if a service receives a unknown JWT signature it can check this new API for a new Public Key and then retry to validate the signature.Topazolite
@BenjaminM : I think it's not safe to read JWT on frontend (if it's on a browser). If you store your token on cookies for exemple, the cookie must be "httpOnly" for security reasons, so not readable from javascript. Since spring-cloud-config allow to use yaml files, I think you can implement your list of keys as a list of objects : #33990112Lange
Of course it is secure. As long as you don't store it in Local Storage and/or are vulnerable to XSS attacks. You can also store the JWT inside a Cookie. Then you must take care of XSRF. There's no golden bullet for security. Or you use a "normal" session cookie and then fetch the contents of the JWT from another URL. Everything has pros and cons. But that's not the topic here. ... Yes Spring Config Server can use YAML (which is simply a superset of JSON). But then I have to figure out how to publish new keys to the services. That's my main problem. Everything else is different topic.Topazolite
I don't understand where is your problem. You just need to had the new keys on config server, then the actuator will do the job of refreshing beans.Lange

© 2022 - 2024 — McMap. All rights reserved.