Checking Session Timeout

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

Checking Session Timeout

juminoz
Am I correct that the only way to check for session timeout is to actually explicitly do something with the session object (i.e. call a method in Session class)? I thought that isAuthenticated() method returns false when user is either not authenticated or that the session has already timed out, but that doesn't seem to be the case. If I don't place a logic to explicitly check, my client still can do everything as if the session hasn't timed out.

Thanks,
Jack
Reply | Threaded
Open this post in threaded view
|

Re: Checking Session Timeout

Les Hazlewood-2
Hi Jack,

The current Subject implementation (DelegatingSubject)
isAuthenticated() implementation assumes that your Subject instances
are very short lived - i.e. they are created and destroyed per request
(it initializes the 'authenticated' boolean in the constructor - not
by checking the session).

Do you use long-lived Subject instances?  I.e. do you store them in
static memory or in an HttpSession?

Regards,

Les

On Tue, May 17, 2011 at 9:24 AM, juminoz <[hidden email]> wrote:
> Am I correct that the only way to check for session timeout is to actually
> explicitly do something with the session object (i.e. call a method in
> Session class)? I thought that isAuthenticated() method returns false when
> user is either not authenticated or that the session has already timed out,
> but that doesn't seem to be the case. If I don't place a logic to explicitly
> check, my client still can do everything as if the session hasn't timed out.
>
> Thanks,
> Jack
Reply | Threaded
Open this post in threaded view
|

Re: Checking Session Timeout

juminoz
I'm currently not explicitly storing Subject anywhere since I thought the framework automatically handles both subject and session. I basically assumed that subject stays around until session expires (may never expire).

Now I'm actually a little confused about how's it supposed to work. Brian mentioned in other thread that I should just keep sessions open and never actually log out so that authorization info stays in the cache.

http://shiro-user.582556.n2.nabble.com/Authorization-Cache-Removed-when-Logged-Out-td6360724.html

If subject is supposed to be short-lived, Brian's suggested approach is not recommended then?

My use cases is as follow:

Note: Client can be web or non-web. Web client may also invoke non-web client to invoke non-web service.

1)
- Client login with at connection time
- Client logout when disconnect

2)
- Client login with when impersonate a user invoking client to call service (username: <app user>/<end user>)
- Client logout after completion of impersonated call

Subject in the second use case is short-lived, but long-lived otherwise. My goal is to cache both authentication and authorization info in the cache so that in high-volume transactions scenario, the bottleneck on ACL is minimized.

Thanks,
Jack
Reply | Threaded
Open this post in threaded view
|

Re: Checking Session Timeout

Les Hazlewood-2
On Tue, May 17, 2011 at 12:58 PM, juminoz <[hidden email]> wrote:
> I'm currently not explicitly storing Subject anywhere since I thought the
> framework automatically handles both subject and session. I basically
> assumed that subject stays around until session expires (may never expire).

The notion of a Subject (i.e. 'user') and its session function as you
expect them to.

I was talking about Shiro's implementation details, which are only
relevant if you _don't_ use SecurityUtils.getSubject() in your code
(for example, if you call SecurityUtils.getSubject() and then save the
returned instance as a class attribute in a long-lived object - this
would cause indeterminate behavior).  If you call
SecurityUtils.getSubject() (or use something that calls that on your
behalf) whenever you need to interact with a Subject instance, you're
ok.

I apologize if I confused anyone!

> Now I'm actually a little confused about how's it supposed to work. Brian
> mentioned in other thread that I should just keep sessions open and never
> actually log out so that authorization info stays in the cache.
>
> http://shiro-user.582556.n2.nabble.com/Authorization-Cache-Removed-when-Logged-Out-td6360724.html
>
> If subject is supposed to be short-lived, Brian's suggested approach is not
> recommended then?

Brian's suggestion is perfectly sound.  But it is sound because the
cache infrastructure doesn't cache Subject instances themselves - it
works because the underlying data that eventually makes up a Subject -
the AuthenticationInfo, AuthorizationInfo, and Session instances - are
what is cached.

> My use cases is as follow:
>
> Note: Client can be web or non-web. Web client may also invoke non-web
> client to invoke non-web service.
>
> 1)
> - Client login with at connection time
> - Client logout when disconnect
>
> 2)
> - Client login with when impersonate a user invoking client to call service
> (username: <app user>/<end user>)
> - Client logout after completion of impersonated call
>
> Subject in the second use case is short-lived, but long-lived otherwise. My
> goal is to cache both authentication and authorization info in the cache so
> that in high-volume transactions scenario, the bottleneck on ACL is
> minimized.

Yep, this won't be a problem.  The key to making this work however is
that for non-web clients, something needs to set up the Subject
instance before the thread executes and something needs to clean up
the thread after it is complete (or fails).

In a web environment, the root Shiro Filter does this setup/teardown
logic per web request automatically.  If not in a web environment, you
(or likely some framework) must do this instead.

You can see an example of this working in a non-web request scenario
by viewing Shiro's Spring Remoting support:

https://svn.apache.org/repos/asf/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/remoting/SecureRemoteInvocationExecutor.java

(see the subject.execute call).

This is also explained in detail in Shiro's Subject documentation:
http://shiro.apache.org/subject.html
Specifically, the Subject.Builder and 'Thread Association' sections.

Does this help?

Cheers,

Les

--
Les Hazlewood
Founder, Katasoft, Inc.
Application Security Products & Professional Apache Shiro Support and Training:
http://www.katasoft.com
Reply | Threaded
Open this post in threaded view
|

Re: Checking Session Timeout

juminoz
Hi Les,

Thanks for the response. To see if I understand it correctly, I setup a simple experiment using a JMS service with 2 JMS clients. I simply ran the test in Eclipse so everything is single-threaded.

Anyway, here's the steps:
1) Start JMS service
2) Start JMS clients (2 instances of the same client, using the same username/password)
3) Send a message to login (server reacts to the message with property "operation=login" by logging the user in)
4) Send a message to execute some logic that requires permission from 2nd client -> successful
5) Send a message to execute some logic that requires permission from 1st client -> successful

I'm not sure everything was executed successfully because the server is single threaded, but I never once had to bind subject to the thread myself. My login method basically executes this line using username/password from the JMS message

SecurityUtils.getSubject().login(<username_password_token>);

and the logic execution invokes

SecurityUtils.getSubject().isPermitted(<permission_string>);

before execute the logic. I'm not sure if I understood your response correctly. I thought for non-web application, I always have to bind the subject to the thread to make it work. Or did you mean I have to do it when I spawn off another thread? I took a look at the Spring example and looks like I would have to bind the subject to the thread of the subsequent calls. That's not what I'm seeing in my experiment. My guess is that I should be doing the following:

1) Login for every request. I can't see how the service knows which client is authenticated. It only knows which user is authenticated. It seems that I also need to clear the thread since subsequent calls is automatically bound to the same subject otherwise.
2) If I spawn off a thread, I need to bind a subject to that thread using sessionId.

Sorry, I usually get it better with an example.

Thanks,
Jack
Reply | Threaded
Open this post in threaded view
|

Re: Is There a Way to Manually Unbind Thread After Login

juminoz
Les,

I think I figured out how I can get things to work with the JMS use case, but I need to be able to unbind thread from the current subject at login. Is there a way to do this? I saw that there is a way to create an bind/unbind SubjectThreadState object with a subject, but how to I get access to it after I login?

Here're the steps of what I think will work:

1) Send a JMS message to login. Unbind the current thread right away so the session remains in the cache, but the thread is clean. A token with session id is sent back to the client, which will be used for subsequent requests related to the same user.
2) For every request, include the token in the JMS message. Service provider then use this token to get the session and subject. Then bind the subject to the current thread.

The issue I saw in my last try as mentioned in the last message in thread is that the thread is associated with a subject permanently until I send a command to logout. This means that any subsequent calls can do everything without having to be authenticated or authorized since Shiro assumed that it's the same user. Because of that, I want to be able to clear the thread state, but leave the session in the cache for further usage.

Thanks,
Jack
Reply | Threaded
Open this post in threaded view
|

Re: Is There a Way to Manually Unbind Thread After Login

juminoz
Just FYI.

I found the unbindSubject() method under ThreadContext class. With the approach I laid out in the last message, things are now working as expected.

I basically unbind the thread when it's completed a task so that when it services the next request, the thread is cleaned and if there is no session ID in subsequent requests, the service simple throw UnauthenticatedException.

Thanks,
Jack
Reply | Threaded
Open this post in threaded view
|

Re: Is There a Way to Manually Unbind Thread After Login

Jared Bunting
That seems like the appropriate way to do it, and basically mimics what
the Servlet Filters do.

On 05/18/2011 05:09 PM, juminoz wrote:

> Just FYI.
>
> I found the unbindSubject() method under ThreadContext class. With the
> approach I laid out in the last message, things are now working as expected.
>
> I basically unbind the thread when it's completed a task so that when it
> services the next request, the thread is cleaned and if there is no session
> ID in subsequent requests, the service simple throw
> UnauthenticatedException.
>
> Thanks,
> Jack
>
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Checking-Session-Timeout-tp6373753p6379729.html
> Sent from the Shiro User mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|

Re: Is There a Way to Manually Unbind Thread After Login

Les Hazlewood
Administrator
In reply to this post by juminoz
The ThreadContext is really an internal support class for Shiro and
not really intended to be used by end-users.

The ideal scenario is I think this:

1.  Based on the incoming message/request/whatever, use the
Subject.Builder to build your subject instance.
2.  Call subject.execute and call whatever method is at the 'root' of
your chain., e.g.

subject.execute(new Runnable() {
    public void run() {
        myRootMethod();
    }
});

from myRootMethod() and anywhere below it in the call stack,
SecurityUtils.getSubject() will work correctly.  When subject.execute
returns, the thread's state will be as it was before calling execute -
it performs automatic cleanup.

This is exactly what the ShiroFilter and the
SecureRemoteInvocationExecutor do to ensure thread association and
automatic cleanup.

Is this not possible in your scenario Jack?

Cheers,

Les
Reply | Threaded
Open this post in threaded view
|

Re: Is There a Way to Manually Unbind Thread After Login

juminoz
Yes, I think I potentially can do it that way, but I will need to look into how to do it with the constraints I have currently.

What I'm doing is building a framework so that developer can use it to develop their applications. Doing it my way definitely seems risky since it's possible that developer forget to unbind the thread after each task.

Anyway, it seems like I need to unbind the subject from the thread right away after login. What's a proper way of doing that? Do I do subject.execute() on a Callable that doesn't do anything? Right now, logging in without unbinding the thread is opening up a hugh security hole. Any call that is serviced by that thread can "pretend" to be the authenticated user without having to do anything. So I should just ignore this fact and do a check on session ID every time? I guess that will work since nothing that requires user to be authenticated will get executed without session ID.

Thanks,
Jack
Reply | Threaded
Open this post in threaded view
|

Re: Is There a Way to Manually Unbind Thread After Login

Les Hazlewood-2
On Wed, May 18, 2011 at 6:42 PM, juminoz <[hidden email]> wrote:
> Yes, I think I potentially can do it that way, but I will need to look into
> how to do it with the constraints I have currently.
>
> What I'm doing is building a framework so that developer can use it to
> develop their applications. Doing it my way definitely seems risky since
> it's possible that developer forget to unbind the thread after each task.
>
> Anyway, it seems like I need to unbind the subject from the thread right
> away after login.

Why would you ever do this?  Most people want the authenticated
Subject instance available for the rest of the request so they can use
it to perform security checks at any point during the request.

In any event, in a non-web request/message scenario, nothing is bound
to the thread by default.  If you call SecurityUtils.getSubject()
however, it will automatically (lazily) create a Subject instance and
bind it to the thread if one does not yet exist.

If you don't want anything bound to the thread in a framework
development scenario, don't use SecurityUtils to set-up the initial
Subject instance.  Instead, it would work like the following:

Message message = //get message somehow

//nothing is bound to the thread at this point

//build a subject instance based on the incoming message
//the 'buildSubject' method would use Subject.Builder to build the
Subject instance
Subject subject = buildSubject(message);

//nothing is bound to the thread at this point

subject.execute(new Runnable() {
    public void run() {
        //the Subject is bound to the thread here!
    }
});

//nothing is bound to the thread at this point.

Notice how SecurityUtils was not used.  SecurityUtils is to make the
lives of application developers easy.  Framework developers will not
use it that often however, and instead rely on building the subject
and calling execute as shown above.

HTH,

Les
Reply | Threaded
Open this post in threaded view
|

Re: Is There a Way to Manually Unbind Thread After Login

Les Hazlewood-2
Also note that if you call execute as shown, any dispatching to other
threads via Shiro's SubjectAwareExecutor, SubjectAwareExecutorService,
and SubjectAwareScheduledExecutorService components will automatically
retain the Subject and perform automatic cleanup.

For example:

subject.execute(new Runnable() {
    public void run() {
        //subject is thread-bound here
        doSomethingConcurrently();
    }
}

//subject is NOT thread-bound here

public void doSomethingConcurrently() {
    //subject is thread-bound here

    Collection<Callable> tasks = //get tasks

    //the returned service instance must be one of Shiro's
    //SubjectAware* implementations, but note that with DI
    //this method isn't aware of Shiro APIs at all:
    ExecutorService execSvc = getExecutorService();

    //each task will be able to call SecurityUtils.getSubject()
    //successfully, with the current Subject being retained.
    //when each task is done, its thread will be cleared of
    //the Subject automatically:
    List<Future> results = invokeAll(tasks);
}

HTH,

Les
Reply | Threaded
Open this post in threaded view
|

Re: Is There a Way to Manually Unbind Thread After Login

juminoz
Hi Les,

Thanks for the pointer.

Does manually creating a subject also create a put a session in the cache? The reasons I wanted the thread unbound right after login are as follow:

1) Request to login does nothing more than just a login. If the session/subject can be cache by manually creating the subject, I think that may work out better as you suggested. Basically, the logic for the client application would then be "if there is no session ID, send username/password with the request". This will eliminate request to login completely. The username/password may then contain 2 usernames and 2 passwords, 1 for app user and 1 for end user (when end user is actually relevant). Subject will then represent the combination. Otherwise, just username/password. All permissions are AND'ed in the framework (app user permission, end user permission, group/subgroup permissions).

2) Subject.login() binds subject to the current thread and even after execution, it doesn't automatically unbind. If this is the only way to create a session, I will probably still want to unbind the thread manually after logging in. The goal is to use session ID for all subsequent requests as long as the session is still alive.

I will trace through how Shiro works internally to find out more.

Thanks,
Jack
Reply | Threaded
Open this post in threaded view
|

Re: Is There a Way to Manually Unbind Thread After Login

Les Hazlewood
Administrator
Hi Jack,

On Thu, May 19, 2011 at 9:15 AM, juminoz <[hidden email]> wrote:
> Hi Les,
>
> Thanks for the pointer.
>
> Does manually creating a subject also create a put a session in the cache?

Nope - a session is only created (currently) when calling
subject.getSession() or subject.login.

> The reasons I wanted the thread unbound right after login are as follow:
>
> 1) Request to login does nothing more than just a login. If the
> session/subject can be cache by manually creating the subject, I think that
> may work out better as you suggested.

If I understand your scenario correctly, it doesn't matter what type
of request is being executed.  If your framework code transparently
creates, binds and then unbinds a Subject for every request (e.g.
exactly as the ShiroFilter does for a web app), it will work in all
cases, login or not.

To illustrate, this will login and cleanup the thread immediately after login:

//build the subject however you want from the message or request,
//perhaps using a sessionId.
Subject subject = new Subject.Builder().whatever....buildSubject();

final AuthenticationToken token = //get/create token based on the request

subject.execute(new Runnable() {
    public void run() {
        SecurityUtils.getSubject().login(token);
    }
});
//thread is 'clean' here

But the problem with this code, from a framework perspective at least,
is that it will *only* perform a login.  It will not work for any
other type of request or message.  Without understanding your scenario
further, one would assume that you want to be able to enable security
while processing any request or message - not just the login ones.  If
that is the case, the above code is not ideal since it can't handle
other types of requests.

HTH,

Les
Reply | Threaded
Open this post in threaded view
|

Re: Is There a Way to Manually Unbind Thread After Login

juminoz
I have a couple simple goal. Enabling security while minimizing overhead of interaction with a user management system. At this point, it's pretty safe to assume that no unauthenticated requests are allowed as well. There might be certain exception cases, but that I can be dealt with later. Performance really matters for this framework.

To achieve the goal, I'm planning to do:

1) Cache session information into Coherence after first request (which also login). This is when I want to unbind the thread completely after execution.
2) Use session ID instead of username/password for all subsequent interaction. Build subject manually using session ID.
3) Invalidate the cache only if there is any change to password.
4) Cache implied permissions (OR of user/group/sub group permission of a subject/dual subjects).
5) Invalidate permissions when there is any change.
6) Session most likely never expire in most cases. Session is destroyed through logout command.
7) All requests are proxied through for authentication while each method requiring authorization explicitly invoke isPermitted().

Interacting with user management system is expensive and is always a bottleneck, especially if they don't have caching mechanism of its own. It's not unusual to see 70% performance drop when enabling authentication/authorization (network overhead, various calculations, etc). The cache is planned to be as close to the using applications as possible (possibly on the same machine or at least location).

Because of this, logging in every time simply doesn't work (i.e. calling user management system). I was told that authentication info will be cached in Shiro 1.2.0. With the new feature, if grabbing the session is as expensive as logging in every time against cached authentication info, then I might as well perform a login every time.

I hope it is clearer about what I'm trying to do. I'm definitely open to ideas if there are shortfalls to this approach.

Thanks,
Jack