I have implemented an authorization server (spring boot application) using the spring security framework. In the application startup, the RSA key pair is generated and the Json Web Key Set (jwks) is also initialized with a public key. This public key is shared through an endpoint to decrypt the token in the resource server.
Now when the authorization server will be deployed in the multiple nodes, there will be multiple jwks initialized and will cause an issue to identify the appropriate public key from the multiple token stores.
What is the best practice to handle such architecture?
Related
How do you manage clientId and clientCredentials of an OIDC(or OAuth2) application's deployment consisting of multiple instances fronted by let's say an L7 load balancer ?
Do you maintain separate clientId/clientCredential for each application instance ?
If yes, how do you manage clientId/clientCredentials for dynamically provisioned instance (E.g. Kubernetes/AWS adding a new application instance in response to a health check failure or a scale-out event)
If you share clientId/clientCredentials across multiple application instances,Isn't that violating the basic rule (i.e. 'secret' is no longer a secret anymore) ?
Also, Compromise of any individual instance by potential attackers, kind of impacts the entire deployment.
If you share clientId/clientCredentials across multiple application
instances,Isn't that violating the basic rule (i.e. 'secret' is no
longer a secret anymore)
Instead of using the secret, you can leverage the Hashicorp Vault which will store and inject the environment variable to the deployment. You can implement encryption at rest and other security options like RBAC on vault UI access.
Yes, secret is base64 encoded not encrypted if you have a large team managing a cluster and RBAC is not set everyone having access to the cluster will be able to decode the secret.
Read more about the has corp vault : https://www.vaultproject.io/
With Kubernetes : https://developer.hashicorp.com/vault/tutorials/kubernetes/kubernetes-raft-deployment-guide?in=vault%2Fkubernetes
Once the vault is set and you have created the secret into it with values you can refer my answer for more details injecting the secret to deployment : https://stackoverflow.com/a/73046067/5525824
I have a Ruby on Rails application with a database that stores sensitive user information (hashed with Devise). I now need to pass some of this sensitive information to another internal service on another server that needs it to make calls to third party APIs, so it needs a way to request that information from the RoR app.
What's the best approach to something like this? My first intuition was to grant an internal API key that would grant access to all sensitive information in the DB (via a private endpoint), the same way developer keys give access to a subset of API endpoints. Is this secure enough as long as I hash the API key? What's the best approach to passing sensitive information around through internal services?
Private APIs
My first intuition was to grant an internal API key that would grant access to all sensitive information in the DB (via a private endpoint), the same way developer keys give access to a subset of API endpoints
Well private endpoints or private APIs don't exist in the sense of only protecting them by using an API key. From a web app you only need to see the html source code to be able to find the API keys. In mobile devices you can see how easy is to reverse engineer API keys in this series of articles about Mobile API Security Techniques. While the articles are in the context of mobile devices, some of the techniques used are also valid in other type of APIs. I hope you can see now how someone could grab the API key and abuse from the API you are trying to secure.
Now even if you don't expose the API key in a mobile app or web app, the API is still discoverable, specially if the endpoint is served by the same API used for the other public endpoints. This is made even easier when you tell in robots.txt that bots should not access some of the endpoints, because this is the first place where hackers look into for trying to enumerate attack vectors into your APIs.
Possible Solutions
Private API Solution
What's the best approach to something like this? My first intuition was to grant an internal API key that would grant access to all sensitive information in the DB (via a private endpoint)
In order to have a private API the server hosting it needs to be protected by a firewall and locked to the other internal server consuming it with certificate pinning and maybe also by IP address. In order to be able to properly secure and lock down the internal server hosting the supposed private API it MUST not support any public requests.
Certificate Pinning:
Pinning effectively removes the "conference of trust". An application which pins a certificate or public key no longer needs to depend on others - such as DNS or CAs - when making security decisions relating to a peer's identity. For those familiar with SSH, you should realize that public key pinning is nearly identical to SSH's StrictHostKeyChecking option. SSH had it right the entire time, and the rest of the world is beginning to realize the virtues of directly identifying a host or service by its public key.
Database Direct Access Solution
What's the best approach to passing sensitive information around through internal services?
Personally I would prefer to access the database directly from the other server and have the database software itself configured to only accept requests from specific internal servers for specific users with the less privileges possible to perform the action they need. Additionally you would employ the firewall locking to and use certificate pinning between the internal servers.
Conclusion
No matter what solution you choose place your database with the sensitive data in server that only hosts that database and is very well lock-down to your internal network.
Anyone needing to access that sensitive data MUST have only read privileges for that specific database table.
I want to secure my application with JWT. This application is only accessed by other server applications that know the secret key before hand. I do not need to add a token generation since the key is already known between the applications. I tried to find some samples for this, but all the examples are complicated (I'm new to spring security) and moreover they do not include anything simple that would fit my use case (known secret key and algorithm, so no provider and storing of the token is needed).
Basically what I want is to decode the token sent by the fellow server, check the secret key, check the sender and check the time (the fellow server will always generate a new token so if that token is stollen then it will be invalid in a small amount of time).
I've thought of implementing this with a custom filter (or interceptor) plus this library and remove spring security entirely, since I can't find any use for it. But I would prefer to use spring security in order to have it available for any future needs and in general achieve what I want by doing it the spring way.
The JWTFilter from JHipster may be a good start!
I'm trying to create a token server for a few selfhosted owin services (console applications)
However, this seems like its only possible if I host in IIS:
The data format used to protect the information contained in the access token. If not provided by the application the default data protection provider depends on the host server. The SystemWeb host on IIS will use ASP.NET machine key data protection, and HttpListener and other self-hosted servers will use DPAPI data protection. If a different access token provider or format is assigned, a compatible instance must be assigned to the OAuthBearerAuthenticationOptions.AccessTokenProvider or OAuthBearerAuthenticationOptions.AccessTokenFormat property of the resource server. - MSDN
Is there any way to share keys across servers if I'm self hosting by sharing some kind of key in the app.config like how I can share a machine key via web.config? If not, that would mean the only option left is to implement my own AccessTokenProvider (assuming I still use the built in OAuth server and self host)?
I've found this answer, which gives an idea on how you can use machine key in self-hosted OWIN app. Please note that a reference to System.Web is required.
After adding MachineKeyProtectionProvider and MachineKeyDataProtector, I just add the protection provider as below.
//...
app.SetDataProtectionProvider(new MachineKeyProtectionProvider());
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active
});
app.UseWebApi(config);
The difficult moment for me here was that the order of initialization matters: UseWebApi should come after SetDataProtectionProvider
I've tried MachineKey protection to no avail under Self-Hosted Web API. What finally worked for me is to specify a DPAPI Protection Provider in both projects:
app.SetDataProtectionProvider(new DpapiDataProtectionProvider("myApp"));
HTH
I am using spring security's open saml library for authentication.
My Service Provider is my spring web application configured with spring saml.
My IDP is OpenSSO.
In the spring-security-saml2-core library, the JKSKeyManager is never called, but the KeyManager gets called.
So is the library using the .jks keystore file as its keys or the 'apollo/nalle123' as its keys? what's their difference?
The org.springframework.security.saml.key.KeyManager is an interface, org.springframework.security.saml.key.JKSKeyManager is its implementation. So if you see calls to KeyManager, in default configuration it means they're hitting the JKSKeyManager.
The apollo/nalle123 key is stored inside the .jks file (samlKeystore.jks in the sample application), configured to be used by the KeyManager. Apollo is alias of the key in the .jks file, nalle123 is its password.
Spring SAML combines usage of keys provided in the KeyManager and keys supplied in SAML metadata.