Is there a way to run separate instances for each connection -or let's say user-, like rmi, via JAX-WS?
HTTP is stateless, therefore each request is on its own. The instance of the service is just one, and that's good.
If you want to store session information (i.e. separate data for each client) you have a couple of options that let you identify each subsequent request as belonging to the same user:
create your own solution - let the client pass a token that identifies his session, and load that session from an in-memory or db-persisted Map<String, ...>.
use OAuth
Related
I have an AuthenticationServerInterceptor for grpc-java, that authenticates any request. However, the request processing itself is split into multiple threads.
For the sake of simplicity lets assume, that there are 3 parts (that are potentially executed by different threads):
Establishing the request and doing the authentication
[1..* times] Processing the parts of the request
Closing the request
What should I pass to the other places in order to allow me to restore the authenticated context in the later cases? (All three parts belong to a single request and they share a grpc-context)
The Authentication instance
The SecurityContext instance
If I pass along the Authentication instance, then I ensure that for each part of the request the original authentication is restored. However, any additional information that might be stored in the (custom) security context will be lost.
If I pass along the SecurityContext instance, then I ensure that for each part of the request the additional information and an authentication are passed along, but the developer must be careful with modifying that context.
Unfortunately I couldn't find any information about which to pass along in the docs.
I cannot just decide on either of those, because the authentication process is part of a library and it doesn't know anything about whether there might be additional details in the context and what the developer might do when processing the request parts.
Here is my current implementation, that is tested to be working+thread safe:
https://github.com/yidongnan/grpc-spring-boot-starter/blob/2ee90f16ee4295370ee47c40829805ff1a9f4f51/grpc-server-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/server/security/interceptors/DefaultAuthenticatingServerInterceptor.java#L59
TLDR: Is spring-security's SecurityContext more thread-scoped or more request-scoped?
The problem is that the default option in Spring Security is thread Local, meaning that if your request create new threads, these new ones will be created with an empty Security context. You can set it to mode Inheritable Thread Local with the following code:
#Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
methodInvokingFactoryBean.setTargetMethod("setStrategyName");
methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
return methodInvokingFactoryBean;
}
I needed to add an authorisation header to all outgoing requests from the client, and I added a ClientRequestFilter as instructed in this answer.
Now I want to change the properties of the filter I created. I tried to re-register a new copy of the filter but that didn't work. I tried to look through the available methods of the Client object but didn't find anything like de-register or remove.
Sample Code:
Client client = ClientBuilder.newClient().register(new ClientObjectMapperProvider());
AuthTokenFilter authTokenFilter = new AuthTokenFilter(authTokenService, authConfig);
client.register(authTokenFilter);
//make some requests
//In another method in another class
AuthTokenFilter newFilter = new AuthTokenFilter(authTokenService, newConfig);
client.register(newFilter);
//make more requests
When I send requests after registering the new filter, I want the auth header to be different according to the new config, but that's not happening.
On further investigation it seems that the client object will not register an object if another of the same type is already registered. Still haven't found a way to de-register though.
Creating Client instances is quite heavyweight so you don't want to do that very often, hence it makes sense that you are caching and reusing the client instance.
If you simply wish to have a separate authentication filter per targeted endpoint then registration doesn't have to be done on the client instance. Before you can actually talk to anything you need to create a WebTarget (which represents a concrete endpoint to which you are to communicate) Once you've created your WebTarget you can register your filter with that.
Configuring webtarget's can also be fairly heavy weight (see here)
but it does mean that you can spawn (and cache) different authentication filters per targeted host.
If you are wanting to dynamically reconfigure your client/webtarget based on some edited configuration (e.g. properties file/configuration REST endpoint) then you
can simply have a cache of WebTarget/Client instances which you regenerate from scratch when the configuration changes. (You need to remember to call client.close() before discarding any old client instance)
Is it possible to access to session id from RealmBase.athenticate method? I need it from my custom realm class in order to store into a database additional info associated to the session and retrieve it during the following requests. I'm using Tomcat 8. Thank you!
No.
Authentication does not require the use of a session, so it's not baked into the API. Authentication is also supposed to be separated from session management, so again it's not baked-into the API.
You might still be able to do this, but it requires some trickery.
Write a Valve that uses a ThreadLocal containing a Request object.
Register the Valve before the AuthenticationValve in the valve chain.
In that Valve, stuff the user's request into the ThreadLocal, then call down the chain.
In your custom Realm, fetch the object from the ThreadLocal.
Always remember to remove the request from the ThreadLocal after the call chain comes back... even if an exception is thrown.
My web application consists of 2 parts:
GWT app that does all the work.
Handmade servlet aimed to handle OpenID authentication facility.
I need to wire p.2 to p.1. I'm reading LoginSecurityFAQ, so I'd like to confirm whether my understanding is correct here.
Once OpenID provider confirms that user is OK and gives me its identity, I should register the session.
To "register" the session, I should store somewhere in my DB a mapping between OpenID identity and a session id (identity="https://www.google.com/accounts/o8/id?id=wwyruiwncuyrwieruyfakefakefake" and session id is a large random string like "HiuhoiuhIUHOIUY87Y*&Ttgi6yUYGIuygUHGugyg^G6g").
That session id should be stored on client side in a cookie.
Every time any request is sent from client side, on server side I should check whether client's session id is still fresh enough (alive) and I should also use it to resolve client's identity in case I need it.
Is it right? Is it secure enough in case session ID is really large?
Your thinking is right, I do it more or less like that too.
Just a few notes:
1) In case you want to persist the identity, do not forget to set the realm right. Depending on OpenID provider you may end up with a different identity for the same user on next login otherwise. I think Google's OpenID requires you to use your server name plus port:
openIdManager.setRealm("http://" + req.getServerName() + ":" + req.getServerPort());
2) Why create your own session management? It is quite a lot of extra work and you might end up writing up something insecure. Use common http servlet sessions.
3) You won't need to manage session timeouts if you use http sessions, but if you need to intercept all GWT RPC calls, the right place might be overriding service method in your RemoteServiceServlet implementation.
I am trying to figure out how to create a stateless spring bean that wraps a group of calls to salesforce web service API. My understanding is that the process for calling salesforce is something like this:
Call the login service to Log into salesforce
Make a series of service calls
Call the logout
To have a stateless wrapper it seems right pattern is to have each method in the bean perform all three steps above. e.g. (pseudocode)
binding.login();
binding.upsert(….);
binding.upsert(….);
binding.logout();
Is this a good practice? It seems it would be a costly way just to keep the bean stateless. Would it be preferable in this instance to make the bean request scope?
I agree with Anup, you should take a look at the sfdc wsc.
If you want go entirely stateless you will need to know the following things about a salesforce connection.
every action must have an endpoint url, something like na6.salesforce.com or na7.salesforce.com
every action must have a valid SID(session id) for the action to complete.
When you login to salesforce the original endpoint is login.salesforce.com and if you are sucessfull you will be returned a valid endpoint(na6.salesforce.com) and a SID.
You can then drop that endpoint/sid into a singleton and share it with as many spring beans as you want. In each bean you will need to create a new SoapBindingStub and set the endpoint and sid before you execute an insert/upsert/update/etc. action.
That sid will expire after a period of inactivity (anywhere from 30-120 minutes depending upon setting) so you should catch any exceptions and relogin using the singleton object.
Dont worry about two beans casuing the singleton relogin at the same time because salesforce will return the sames sid to both.
Have you tried SFDC WSC library? It's easy to use, and fits the use case that you are trying to accomplish.