You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by mbrictson <ma...@55minutes.com> on 2011/02/10 00:05:33 UTC

How to deal with remembered principals if realm has since changed?

Hello,

I am loving the simplicity and the great code-level documentation that Shiro
provides. Turning on the "remember me" feature just worked! But now that I
am switching from a one realm implementation to another I am finding that
the remember me feature is posing a problem.

>From what I can tell, Shiro trusts the remember me cookie as long as it can
be decrypted and deserialized without error. But what if the realm in my
application has changed such that those remembered principals are no longer
valid?

Specifically, my realm started out by using a simple String as the
principal, but in a new version of my app it has changed to using a complex
type, MyAppPrincipal. The remembered PrincipalCollection deserialized from
the cookie doesn't have this -- it has the old String value.

I can't find a simple hook in Shiro that allows the remembered principals to
be validated. Specifically, if my code is annotated with @RequiresUser, this
check passes as long as the subject has any non-null principal, even if that
principal is considered unacceptable by my new realm.

Does that make sense?

Essentially what I'm hoping Shiro could do is:

1. When deserializing the remembered principal check whether the realm name
in the remembered principal matches one of the realms currently configured
in the app. If there is no matching realm, the remembered principal is
considered invalid and the cookie destroyed.

2. Perhaps in addition, provide a hook in the Authenticator interface (?)
where remembered principals can be validated, like: boolean
isRememberedPrincipalsValid(PrincipalCollection).

What do you think?

Or is there already a simple solution to this that I'm missing? :)

-- 
Matt
-- 
View this message in context: http://shiro-user.582556.n2.nabble.com/How-to-deal-with-remembered-principals-if-realm-has-since-changed-tp6009937p6009937.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: How to deal with remembered principals if realm has since changed?

Posted by mbrictson <ma...@55minutes.com>.
Thanks Les, for your thoughtful reply.

I agree overriding AbstractRememberMeManager.deserialize(byte[]) is the easiest solution for the upgrade problem. I can provide whatever logic is necessary there to validate the principals.

But perhaps this issue that I raised is more of a symptom of a fundamental issue with the @RequiresUser check. Outdated principals cause a problem with @RequiresUser because by simply checking subject.getPrincipal() != null is not sufficient.

Consider if instead of @RequiresUser I use @RequiresRoles("user"), with the understanding that "user" is a role all users have. Now the remember me issue is no longer a problem, because my realm's doGetAuthorizationInfo() will see the principal is outdated/bogus and appropriately reject access for @RequiresRoles("user").

Furthermore consider the case where a user's account has become locked: @RequiresUser will still let the user in, because the realm is never consulted, whereas @RequiresRoles("user") would allow the realm to check account locked status in doGetAuthorizationInfo(). 

Ultimately I think what I've learned from this is that @RequiresUser (or it's procedural equivalent of subject.getPrincipal() != null) should probably be avoided.

-- 
Matt


-- 
View this message in context: http://shiro-user.582556.n2.nabble.com/How-to-deal-with-remembered-principals-if-realm-has-since-changed-tp6009937p6010245.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: How to deal with remembered principals if realm has since changed?

Posted by Les Hazlewood <lh...@apache.org>.
Hi Matt,

I don't know if solution #1 is a viable option - a realm's
implementation can easily change while its name might stay the same in
configuration, so that's not necessarily a trigger to execute Remember
Me-related logic.  Also, I don't think #2 is viable because the
Authenticator interface doesn't 'know' about remember me concerns.
Remember Me is more of an implementation detail/feature of the
particular Authenticator implementation.

But that being said, I see a relatively simple solution that is easily
pluggable:

The AbstractRememberMeManager (and its subclasses by extension) accept
a 'serializer' attribute that you can configure.

Perhaps you can create an UpgradeAwareRememberMeSerializer that
subclasses Shiro's DefaultSerializer.  Override the 'deserialize'
method to get the old instance, upgrade it to what your app expects,
and then return that new representation.  For example:

@Override
public PrincipalCollection deserialize(byte[] bytes) {
    PrincipalCollection pc = super.deserialize(bytes);
    if (principalsAreFromAppVersion1(pc) ) {
        pc = convertToAppVersion2(pc);
    }
    return to pc;
}

Then you can plug that in to your shiro.ini config:

upgradeAwareRememberMeSerializer = com.my.UpgradeAwareRememberMeSerializer

securityManager.rememberMeManager.serializer = $upgradeAwareRememberMeSerializer

This isn't a general purpose solution for all Shiro users of course,
but it seems like the most relevant solution for your particular
situation.  If you think a general purpose solution should be in
place, please open a Jira feature request - the community might have
to brainstorm a bit to figure out how to do it in a generic way first.

Cheers,

-- 
Les Hazlewood
Founder, Katasoft, Inc.
Application Security Products & Professional Apache Shiro Support and Training:
http://www.katasoft.com

On Wed, Feb 9, 2011 at 3:05 PM, mbrictson <ma...@55minutes.com> wrote:
>
> Hello,
>
> I am loving the simplicity and the great code-level documentation that Shiro
> provides. Turning on the "remember me" feature just worked! But now that I
> am switching from a one realm implementation to another I am finding that
> the remember me feature is posing a problem.
>
> From what I can tell, Shiro trusts the remember me cookie as long as it can
> be decrypted and deserialized without error. But what if the realm in my
> application has changed such that those remembered principals are no longer
> valid?
>
> Specifically, my realm started out by using a simple String as the
> principal, but in a new version of my app it has changed to using a complex
> type, MyAppPrincipal. The remembered PrincipalCollection deserialized from
> the cookie doesn't have this -- it has the old String value.
>
> I can't find a simple hook in Shiro that allows the remembered principals to
> be validated. Specifically, if my code is annotated with @RequiresUser, this
> check passes as long as the subject has any non-null principal, even if that
> principal is considered unacceptable by my new realm.
>
> Does that make sense?
>
> Essentially what I'm hoping Shiro could do is:
>
> 1. When deserializing the remembered principal check whether the realm name
> in the remembered principal matches one of the realms currently configured
> in the app. If there is no matching realm, the remembered principal is
> considered invalid and the cookie destroyed.
>
> 2. Perhaps in addition, provide a hook in the Authenticator interface (?)
> where remembered principals can be validated, like: boolean
> isRememberedPrincipalsValid(PrincipalCollection).
>
> What do you think?
>
> Or is there already a simple solution to this that I'm missing? :)
>
> --
> Matt
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/How-to-deal-with-remembered-principals-if-realm-has-since-changed-tp6009937p6009937.html
> Sent from the Shiro User mailing list archive at Nabble.com.

Re: How to deal with remembered principals if realm has since changed?

Posted by mbrictson <ma...@55minutes.com>.
Armando,


armandoxxx wrote:
> 
> Why is is so important for you to have remember me functionality
> 

I think "remember me" is one of the great features of Shiro. The fact that
this is such a common paradigm on the web (Amazon being a typical example)
means that users have learned to expect this feature from consumer-facing
apps. So I think it is important as developers that we figure out how to use
this feature effectively.

"Remember me" is all about convenience for the end user; it is by no means a
way to implement authentication. It is certainly possible for someone to
forge a cookie, which is why you use remember me for personalization but not
for giving access to sensitive data.

My point was that applications are developed over time, and as you release
new versions your security implementation under the hood is likely going to
change and improve. Some of these changes might break backwards
compatibility with the remember me system, as I illustrated in my example.
The solution that Les suggested would allow for the system to gracefully
migrate these now incompatible remember me cookies, thereby providing a
seamless experience to the user: the personalization features keep working.


armandoxxx wrote:
> 
> if application changed, then users should relogin
> 

Sure, let's say you do want to force the user to relogin after you change
your implementation. This still requires some extra work. As I explained,
Shiro will blindly accept a remember me cookie and place that remembered
principal in the Subject even if that principal is no longer valid. In order
to force the user to relogin you need subclass the RememberMeManager and
hook into the deserialization process, as Les described, in order to
validate and reject that principal.
-- 
View this message in context: http://shiro-user.582556.n2.nabble.com/How-to-deal-with-remembered-principals-if-realm-has-since-changed-tp6009937p6010696.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: How to deal with remembered principals if realm has since changed?

Posted by armandoxxx <ar...@dropchop.com>.
Why is is so important for you to have remember me functionality available
across different applications (in your case new version) ... If you ask me
there's no need for that in real world .. if application changed, then users
should relogin .. but if they forgot their passwords, then it's your
application job to give them "Forgot password" feature.

I personally think your kind of feature is a potential security risk in a
matter when you implement you "remember me (from old application) strategy"
in a new application and someone else gets the code from old application
(this happens in real world), he can always hack into your system creating
remember me cookies with an old application and login to new one ...
Specially when your old application has a really simple principal ...

Regards

Armando

On Thu, Feb 10, 2011 at 12:05 AM, mbrictson [via Shiro User] <
ml-node+6009937-774117617-176327@n2.nabble.com> wrote:

> Hello,
>
> I am loving the simplicity and the great code-level documentation that
> Shiro provides. Turning on the "remember me" feature just worked! But now
> that I am switching from a one realm implementation to another I am finding
> that the remember me feature is posing a problem.
>
> From what I can tell, Shiro trusts the remember me cookie as long as it can
> be decrypted and deserialized without error. But what if the realm in my
> application has changed such that those remembered principals are no longer
> valid?
>
> Specifically, my realm started out by using a simple String as the
> principal, but in a new version of my app it has changed to using a complex
> type, MyAppPrincipal. The remembered PrincipalCollection deserialized from
> the cookie doesn't have this -- it has the old String value.
>
> I can't find a simple hook in Shiro that allows the remembered principals
> to be validated. Specifically, if my code is annotated with @RequiresUser,
> this check passes as long as the subject has any non-null principal, even if
> that principal is considered unacceptable by my new realm.
>
> Does that make sense?
>
> Essentially what I'm hoping Shiro could do is:
>
> 1. When deserializing the remembered principal check whether the realm name
> in the remembered principal matches one of the realms currently configured
> in the app. If there is no matching realm, the remembered principal is
> considered invalid and the cookie destroyed.
>
> 2. Perhaps in addition, provide a hook in the Authenticator interface (?)
> where remembered principals can be validated, like: boolean
> isRememberedPrincipalsValid(PrincipalCollection).
>
> What do you think?
>
> Or is there already a simple solution to this that I'm missing? :)
>
> --
> Matt
>
> ------------------------------
>  If you reply to this email, your message will be added to the discussion
> below:
>
> http://shiro-user.582556.n2.nabble.com/How-to-deal-with-remembered-principals-if-realm-has-since-changed-tp6009937p6009937.html
>  To start a new topic under Shiro User, email
> ml-node+582556-860113682-176327@n2.nabble.com
> To unsubscribe from Shiro User, click here<http://shiro-user.582556.n2.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=582556&code=YXJtYW5kby5vdGFAZHJvcGNob3AuY29tfDU4MjU1Nnw0NjA2NDQ4NTQ=>.
>
>

-- 
View this message in context: http://shiro-user.582556.n2.nabble.com/How-to-deal-with-remembered-principals-if-realm-has-since-changed-tp6009937p6010615.html
Sent from the Shiro User mailing list archive at Nabble.com.