Advice on Shira with FB Connect, Session Clustering Efficiency

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Advice on Shira with FB Connect, Session Clustering Efficiency

matan_a
Hi All,

I'm currently using Spring Security which until now was doing a fine job for my needs.  Once we started doing session clustering w/o any session stickiness, we ran into issues with Spring Security.  Specifically, it saves a lot of security related classes in the Session which makes Session serialization inefficient.  Even more so, trying to use a performant serialization method like Kryo is difficult because of the not-so-POJO-friendly design of the Spring Security classes.

Anyway, Shiro seems like one good alternative and i've been studying it for the last day.  My question concerns integration with Facebook Connect and Session usage.

Our site is Facebook Connect only so that is the only requirement for authentication.  We do cross reference some user preferences for app speficic authorization information.

It seems like i'd need a custom filter to retrieve the Facebook credentials and a custom Realm that doesn't do much more than see if the user already exists in the store + some other roles logic.

So any help would be appreciated for helping me answer:

1. What is the ideal way anyone here has done this (i'm sure i'm not the first)?
2. I have some custom "login" logic to check if the user exists and create the user if not + some other locked status stuff.  I assume this goes in the Realm?
3. What kind of data does Shiro actually save in the Session?  We're very keen on keeping it as lean as possible and easily serializable using Kryo or other performant library (these libraries usually use default constructors and reflection).
4. We have some functionality that sends requests that don't contain the SessionID (from flash) so we just include the SessionID as a request parameter and "inject" the security context using a filter in the request thread.  Is that possible with Shiro without doing a complete "login" process?  It should allow Session lookup by id.

Thanks in advance and again, much appreciated!
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Advice on Shira with FB Connect, Session Clustering Efficiency

Les Hazlewood-2
Hi there,

> 1. What is the ideal way anyone here has done this (i'm sure i'm not the
> first)?

I have not done this, but yes, you would create a Realm and/or filter
as necessary to handle the Facebook Connect protocol.  If you (or
someone) does this and wishes to contribute it back to the project,
please create a Jira issue!

> 2. I have some custom "login" logic to check if the user exists and create
> the user if not + some other locked status stuff.  I assume this goes in the
> Realm?

You could do it there.  I'd probably delegate that logic to a
component that plugs in to your Realm so you keep that logic separate
from the Realm's needs.

Then, once the user is authenticated (or authenticated and then
created), you return the identity you need in the form of a Shiro
AuthenticationInfo.

> 3. What kind of data does Shiro actually save in the Session?  We're very
> keen on keeping it as lean as possible and easily serializable using Kryo or
> other performant library (these libraries usually use default constructors
> and reflection).

Very very little.  Here are the session usages I can think of off the
top of my head:

1. By default it will store the PrincipalCollection (the collection of
account identities discovered during authentication) after login so
the Subject's identity is available for the remainder of the session.

2. It will use the session to store a request if the request needs to
be redirected and referenced later.  For example, if an
unauthenticated user visits an authentication-required page, they
could be redirected to the login page.  Before redirect, the request
will be saved in the session so that after successful login, Shiro can
auto-redirect the user back to the same page they originally
requested.

3. During 'runAs' functionality.  RunAs is implemented as a stack of
PrincipalCollections that get pushed on or popped off of the stack as
runAs identities are accumulated or released, respectively.  That
stack is presently stored in the Subject's session if runAs
functionality is engaged.  If runAs is not used, the session is not
touched.

I think that's it.  To ensure that sessions are clustered as
efficiently as possible, ensure that the PrincipalCollection returned
from your Realm during authentication is as lean as possible.  Most
people store a primitive value that is a 'pointer' to the actual data
- e.g. a user id or username or similar - to ensure the session
remains lean.

> 4. We have some functionality that sends requests that don't contain the
> SessionID (from flash) so we just include the SessionID as a request
> parameter and "inject" the security context using a filter in the request
> thread.  Is that possible with Shiro without doing a complete "login"
> process?  It should allow Session lookup by id.

Absolutely! Shiro's session support really shines for these types of
'frameworky' issues.

You will need to replicate what the ShiroFilter does for web requests:
 when encountering a session ID associated with the request, build a
Subject instance that corresponds to the referenced session and ensure
the Subject is bound to the thread for access at any time during the
thread's execution.  This is trivial w/ the Shiro APIs:

SecurityManager shiroSecurityManager = //get from app-specific location
String sessionId = //get from request payload or header

Subject callingSubject = new
Subject.Builder(shiroSecurityManager).sessionId(sessionId).buildSubject();

subject.execute(new Callable() {
    public Object call() throws Exception {
        //continue the filter chain here
    }
});

The execute call will ensure that the Subject instance is bound to the
current thread and then unbound after the method returns.  This
guarantees thread 'cleanliness' in thread-pooling environments.

More information on this approach is covered in Shiro's documentation:

http://shiro.apache.org/subject.html

specifically, the "Custom Subject Instances" section.

You'll also find value in seeing how the ShiroFilter does this for web requests:

http://shiro.apache.org/static/current/xref/org/apache/shiro/web/servlet/AbstractShiroFilter.html#260

As well as Shiro's Spring Remoting-specific support (shows a remote
method invocation scenario demonstrating the same flow, but without a
web request):

http://shiro.apache.org/static/current/xref/org/apache/shiro/spring/remoting/SecureRemoteInvocationExecutor.html#78

You'll need to do something identical for the Flex-specific request.

I know people have already done this to support Shiro in the SmartFox
Server for Flash-based mmo games, but I don't know where the code is.
If you can find it, that might help as well.  In any event, I'm sure
that code looks like the above two code samples, so they might get you
far enough.

HTH!

Cheers,

--
Les Hazlewood
CTO, Katasoft | http://www.katasoft.com | 888.391.5282
twitter: @lhazlewood | http://twitter.com/lhazlewood
katasoft blog: http://www.katasoft.com/blogs/lhazlewood
personal blog: http://leshazlewood.com
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Advice on Shira with FB Connect, Session Clustering Efficiency

matan_a
Wow, I have to say, this was an awesome reply.  
I appreciate the help and the level of detail.

I should be good to go from here :)

Re: Facebook Connect, I personally didn't do a generic implementation - just a FB specific one.  Now that FB officially supports OAuth2, i might go for that.  If so, i can post the code.

Cheers,
Matan

On Mon, Sep 26, 2011 at 3:09 PM, Les Hazlewood-2 [via Shiro User] <[hidden email]> wrote:
Hi there,

> 1. What is the ideal way anyone here has done this (i'm sure i'm not the
> first)?

I have not done this, but yes, you would create a Realm and/or filter
as necessary to handle the Facebook Connect protocol.  If you (or
someone) does this and wishes to contribute it back to the project,
please create a Jira issue!

> 2. I have some custom "login" logic to check if the user exists and create
> the user if not + some other locked status stuff.  I assume this goes in the
> Realm?

You could do it there.  I'd probably delegate that logic to a
component that plugs in to your Realm so you keep that logic separate
from the Realm's needs.

Then, once the user is authenticated (or authenticated and then
created), you return the identity you need in the form of a Shiro
AuthenticationInfo.

> 3. What kind of data does Shiro actually save in the Session?  We're very
> keen on keeping it as lean as possible and easily serializable using Kryo or
> other performant library (these libraries usually use default constructors
> and reflection).

Very very little.  Here are the session usages I can think of off the
top of my head:

1. By default it will store the PrincipalCollection (the collection of
account identities discovered during authentication) after login so
the Subject's identity is available for the remainder of the session.

2. It will use the session to store a request if the request needs to
be redirected and referenced later.  For example, if an
unauthenticated user visits an authentication-required page, they
could be redirected to the login page.  Before redirect, the request
will be saved in the session so that after successful login, Shiro can
auto-redirect the user back to the same page they originally
requested.

3. During 'runAs' functionality.  RunAs is implemented as a stack of
PrincipalCollections that get pushed on or popped off of the stack as
runAs identities are accumulated or released, respectively.  That
stack is presently stored in the Subject's session if runAs
functionality is engaged.  If runAs is not used, the session is not
touched.

I think that's it.  To ensure that sessions are clustered as
efficiently as possible, ensure that the PrincipalCollection returned
from your Realm during authentication is as lean as possible.  Most
people store a primitive value that is a 'pointer' to the actual data
- e.g. a user id or username or similar - to ensure the session
remains lean.

> 4. We have some functionality that sends requests that don't contain the
> SessionID (from flash) so we just include the SessionID as a request
> parameter and "inject" the security context using a filter in the request
> thread.  Is that possible with Shiro without doing a complete "login"
> process?  It should allow Session lookup by id.

Absolutely! Shiro's session support really shines for these types of
'frameworky' issues.

You will need to replicate what the ShiroFilter does for web requests:
 when encountering a session ID associated with the request, build a
Subject instance that corresponds to the referenced session and ensure
the Subject is bound to the thread for access at any time during the
thread's execution.  This is trivial w/ the Shiro APIs:

SecurityManager shiroSecurityManager = //get from app-specific location
String sessionId = //get from request payload or header

Subject callingSubject = new
Subject.Builder(shiroSecurityManager).sessionId(sessionId).buildSubject();

subject.execute(new Callable() {
    public Object call() throws Exception {
        //continue the filter chain here
    }
});

The execute call will ensure that the Subject instance is bound to the
current thread and then unbound after the method returns.  This
guarantees thread 'cleanliness' in thread-pooling environments.

More information on this approach is covered in Shiro's documentation:

http://shiro.apache.org/subject.html

specifically, the "Custom Subject Instances" section.

You'll also find value in seeing how the ShiroFilter does this for web requests:

http://shiro.apache.org/static/current/xref/org/apache/shiro/web/servlet/AbstractShiroFilter.html#260

As well as Shiro's Spring Remoting-specific support (shows a remote
method invocation scenario demonstrating the same flow, but without a
web request):

http://shiro.apache.org/static/current/xref/org/apache/shiro/spring/remoting/SecureRemoteInvocationExecutor.html#78

You'll need to do something identical for the Flex-specific request.

I know people have already done this to support Shiro in the SmartFox
Server for Flash-based mmo games, but I don't know where the code is.
If you can find it, that might help as well.  In any event, I'm sure
that code looks like the above two code samples, so they might get you
far enough.

HTH!

Cheers,

--
Les Hazlewood
CTO, Katasoft | http://www.katasoft.com | <a href="tel:888.391.5282" value="+18883915282" target="_blank">888.391.5282
twitter: @lhazlewood | http://twitter.com/lhazlewood
katasoft blog: http://www.katasoft.com/blogs/lhazlewood
personal blog: http://leshazlewood.com



If you reply to this email, your message will be added to the discussion below:
http://shiro-user.582556.n2.nabble.com/Advice-on-Shira-with-FB-Connect-Session-Clustering-Efficiency-tp6832777p6833728.html
To unsubscribe from Advice on Shira with FB Connect, Session Clustering Efficiency, click here.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Advice on Shira with FB Connect, Session Clustering Efficiency

kaosko
In reply to this post by matan_a
On Mon, Sep 26, 2011 at 10:32 AM, matan_a <[hidden email]> wrote:
> It seems like i'd need a custom filter to retrieve the Facebook credentials
> and a custom Realm that doesn't do much more than see if the user already
> exists in the store + some other roles logic.

Based on that I'm assuming you are currently using fb.login or
similar, purely client-side integration.
> So any help would be appreciated for helping me answer:
> 1. What is the ideal way anyone here has done this (i'm sure i'm not the
> first)?

Ideal depends on the use case, but if you want a deeper integration,
you need to initiate the oauth flow yourself on the server side. I've
created a shiro/fb integration for Tapestry5 at
http://tynamo.org/tynamo-federatedaccounts+guide (with a larger scope
than FB only). Perhaps you can lift some code from
http://svn.codehaus.org/tynamo/trunk/tynamo-federatedaccounts/tynamo-federatedaccounts-facebook/src/main/java/org/tynamo/security/federatedaccounts/facebook/base/AbstractFacebookOauthPage.java
and related classes. The idea is that the account is merged (answering
to the same need as in your second question below), so you first login
via fb, but then have a local account component that participates in
authorizing (or even authenticating) the user via a Shiro realm (as
implemented in http://svn.codehaus.org/tynamo/trunk/tynamo-federatedaccounts/tynamo-federatedaccounts-facebook/src/main/java/org/tynamo/security/federatedaccounts/facebook/services/FacebookRealm.java).
The realm uses restfb (http://restfb.com/) for communicating via FB's
graph api.

Kalle

> 2. I have some custom "login" logic to check if the user exists and create
> the user if not + some other locked status stuff.  I assume this goes in the
> Realm?
> 3. What kind of data does Shiro actually save in the Session?  We're very
> keen on keeping it as lean as possible and easily serializable using Kryo or
> other performant library (these libraries usually use default constructors
> and reflection).
> 4. We have some functionality that sends requests that don't contain the
> SessionID (from flash) so we just include the SessionID as a request
> parameter and "inject" the security context using a filter in the request
> thread.  Is that possible with Shiro without doing a complete "login"
> process?  It should allow Session lookup by id.
>
> Thanks in advance and again, much appreciated!
>
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Advice-on-Shira-with-FB-Connect-Session-Clustering-Efficiency-tp6832777p6832777.html
> Sent from the Shiro User mailing list archive at Nabble.com.
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Advice on Shira with FB Connect, Session Clustering Efficiency

matan_a
Thanks Kalle.  I'm sure i'll find that very useful.
Loading...