Authenticating a Subject without a session with a WebSecurityManager

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

Authenticating a Subject without a session with a WebSecurityManager

Martin Nielsen
Hi all

I have an application which uses a WebSecurityManager in conjunction with Apache Wicket. That works all well and good, but now I have encountered a single issue where i need to authenticate a user through a different entrance, which does not have any notion of http sessions. When i try to login a Subject without a session like this:

Subject shiroSubject = null;
Subject.Builder subjectBuilder = new Subject.Builder(manager).sessionCreationEnabled(false);
shiroSubject = subjectBuilder.buildSubject();
...
shiroSubject.login(new UsernamePasswordToken(user, password));

I tried every permutation of sessionCreationEnabled


I get the following exception:


javax.security.auth.login.LoginException: java.lang.IllegalArgumentException: SessionContext must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.createSession(ServletContainerSessionManager.java:103)
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.start(ServletContainerSessionManager.java:64)
at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:152)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:336)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:312)
at org.apache.shiro.mgt.DefaultSubjectDAO.mergePrincipals(DefaultSubjectDAO.java:204)
at org.apache.shiro.mgt.DefaultSubjectDAO.saveToSession(DefaultSubjectDAO.java:166)
at org.apache.shiro.mgt.DefaultSubjectDAO.save(DefaultSubjectDAO.java:147)
at org.apache.shiro.mgt.DefaultSecurityManager.save(DefaultSecurityManager.java:383)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:350)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)

I then looked at WebSubject.Builder i can't create a builder without a Request and Response.


So the question is: When you are using a WebSecurityManager, how do you authenticate a Subject in a case where there is no Request/Response available?

The only way that I can see is to highjack the WebSecurityManager's Authenticator and Authorizer and call their methods directly, completely ignoring the Subject, but that feels so wrong that I am guessing that i am way off :)
Reply | Threaded
Open this post in threaded view
|

Re: Authenticating a Subject without a session with a WebSecurityManager

Martin Nielsen
Right. So i got a little further, and discovered that the problem is the SessionStorageEvaluator on the DefaultSubjectDAO. It is set to a DefaultWebSessionStorageEvaluator, seems like it should handle the problem with this code:

//SHIRO-350: non-web subject instances can't be saved to web-only session managers:
        //since 1.2.1:
        if (!(subject instanceof WebSubject) && (this.sessionManager != null && !(this.sessionManager instanceof NativeSessionManager))) {
            return false;
        }

The problem is that when i login, the DelegatingSubject i create is automatically changed to a WebDelegatingSubject, which means that this code is skipped.

What happens is this:

shiroSubject = subjectBuilder.buildSubject();
Builds a DelegatingSubject, which passes through the Evaluator without issue.

shiroSubject.login(new UsernamePasswordToken(user, password));
Seems to have some unfriendly behavior as the DefaultWebSecurityManager delegates its login to DefaultSecurityManager, which creates a new Subject in its login method which becomes a WebDelegatingSubject thanks to the DefaultWebSubjectFactory set by the  DefaultWebSecurityManager, which also overrides createSubjectContext()  to return a DefaultWebSubjectContext.

In short: It seems no matter what i do, a WebDelegatingSubject is ALWAYS created when i call the login method, causing the  DefaultWebSessionStorageEvaluator to attempt to create a session for a  WebDelegatingSubject which does not have a session as it was created from a normal DelegatingSubject.

This does seem more a bug than by design, and if people shout "bug" i will gladly create a decent bug-report. But for now: How on earth do i get around this?


On Thu, Apr 5, 2018 at 9:23 AM, Martin Nielsen <[hidden email]> wrote:
Hi all

I have an application which uses a WebSecurityManager in conjunction with Apache Wicket. That works all well and good, but now I have encountered a single issue where i need to authenticate a user through a different entrance, which does not have any notion of http sessions. When i try to login a Subject without a session like this:

Subject shiroSubject = null;
Subject.Builder subjectBuilder = new Subject.Builder(manager).sessionCreationEnabled(false);
shiroSubject = subjectBuilder.buildSubject();
...
shiroSubject.login(new UsernamePasswordToken(user, password));

I tried every permutation of sessionCreationEnabled


I get the following exception:


javax.security.auth.login.LoginException: java.lang.IllegalArgumentException: SessionContext must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.createSession(ServletContainerSessionManager.java:103)
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.start(ServletContainerSessionManager.java:64)
at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:152)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:336)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:312)
at org.apache.shiro.mgt.DefaultSubjectDAO.mergePrincipals(DefaultSubjectDAO.java:204)
at org.apache.shiro.mgt.DefaultSubjectDAO.saveToSession(DefaultSubjectDAO.java:166)
at org.apache.shiro.mgt.DefaultSubjectDAO.save(DefaultSubjectDAO.java:147)
at org.apache.shiro.mgt.DefaultSecurityManager.save(DefaultSecurityManager.java:383)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:350)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)

I then looked at WebSubject.Builder i can't create a builder without a Request and Response.


So the question is: When you are using a WebSecurityManager, how do you authenticate a Subject in a case where there is no Request/Response available?

The only way that I can see is to highjack the WebSecurityManager's Authenticator and Authorizer and call their methods directly, completely ignoring the Subject, but that feels so wrong that I am guessing that i am way off :)

Reply | Threaded
Open this post in threaded view
|

Re: Authenticating a Subject without a session with a WebSecurityManager

Brian Demers
Hey Martin,

Though I agree throwing an exception in this case probably isn't the best default.

I had a similar problem a while back and IIRC I solved it by configuring a second SecurityManager (one configured for web access and the second for non-web).  I had a few other differences configured as well, but this approach means you need to manage the lifecycle of the second instance.  

If that first link doesn't get you what you need, think about the second option.  But either way please create a JIRA!


On Thu, Apr 5, 2018 at 5:49 AM, Martin Nielsen <[hidden email]> wrote:
Right. So i got a little further, and discovered that the problem is the SessionStorageEvaluator on the DefaultSubjectDAO. It is set to a DefaultWebSessionStorageEvaluator, seems like it should handle the problem with this code:

//SHIRO-350: non-web subject instances can't be saved to web-only session managers:
        //since 1.2.1:
        if (!(subject instanceof WebSubject) && (this.sessionManager != null && !(this.sessionManager instanceof NativeSessionManager))) {
            return false;
        }

The problem is that when i login, the DelegatingSubject i create is automatically changed to a WebDelegatingSubject, which means that this code is skipped.

What happens is this:

shiroSubject = subjectBuilder.buildSubject();
Builds a DelegatingSubject, which passes through the Evaluator without issue.

shiroSubject.login(new UsernamePasswordToken(user, password));
Seems to have some unfriendly behavior as the DefaultWebSecurityManager delegates its login to DefaultSecurityManager, which creates a new Subject in its login method which becomes a WebDelegatingSubject thanks to the DefaultWebSubjectFactory set by the  DefaultWebSecurityManager, which also overrides createSubjectContext()  to return a DefaultWebSubjectContext.

In short: It seems no matter what i do, a WebDelegatingSubject is ALWAYS created when i call the login method, causing the  DefaultWebSessionStorageEvaluator to attempt to create a session for a  WebDelegatingSubject which does not have a session as it was created from a normal DelegatingSubject.

This does seem more a bug than by design, and if people shout "bug" i will gladly create a decent bug-report. But for now: How on earth do i get around this?


On Thu, Apr 5, 2018 at 9:23 AM, Martin Nielsen <[hidden email]> wrote:
Hi all

I have an application which uses a WebSecurityManager in conjunction with Apache Wicket. That works all well and good, but now I have encountered a single issue where i need to authenticate a user through a different entrance, which does not have any notion of http sessions. When i try to login a Subject without a session like this:

Subject shiroSubject = null;
Subject.Builder subjectBuilder = new Subject.Builder(manager).sessionCreationEnabled(false);
shiroSubject = subjectBuilder.buildSubject();
...
shiroSubject.login(new UsernamePasswordToken(user, password));

I tried every permutation of sessionCreationEnabled


I get the following exception:


javax.security.auth.login.LoginException: java.lang.IllegalArgumentException: SessionContext must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.createSession(ServletContainerSessionManager.java:103)
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.start(ServletContainerSessionManager.java:64)
at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:152)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:336)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:312)
at org.apache.shiro.mgt.DefaultSubjectDAO.mergePrincipals(DefaultSubjectDAO.java:204)
at org.apache.shiro.mgt.DefaultSubjectDAO.saveToSession(DefaultSubjectDAO.java:166)
at org.apache.shiro.mgt.DefaultSubjectDAO.save(DefaultSubjectDAO.java:147)
at org.apache.shiro.mgt.DefaultSecurityManager.save(DefaultSecurityManager.java:383)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:350)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)

I then looked at WebSubject.Builder i can't create a builder without a Request and Response.


So the question is: When you are using a WebSecurityManager, how do you authenticate a Subject in a case where there is no Request/Response available?

The only way that I can see is to highjack the WebSecurityManager's Authenticator and Authorizer and call their methods directly, completely ignoring the Subject, but that feels so wrong that I am guessing that i am way off :)


Reply | Threaded
Open this post in threaded view
|

Re: Authenticating a Subject without a session with a WebSecurityManager

Martin Nielsen
Hi Brian

I looked a bit further at the issue and i will create a bug report when i have the chance. The websubject created by the login method ends up having both httpservlet response and requests set to null. That seems to be a pretty straight forward error. I fixed the issue by creating a new websubject factory which creates delegatingsubjects instead of websubjects if the existing subject was itself a delegatingsubject. No second securitymanager needed, at least for now.

On Thu, 5 Apr 2018, 16:22 Brian Demers, <[hidden email]> wrote:
Hey Martin,

Though I agree throwing an exception in this case probably isn't the best default.

I had a similar problem a while back and IIRC I solved it by configuring a second SecurityManager (one configured for web access and the second for non-web).  I had a few other differences configured as well, but this approach means you need to manage the lifecycle of the second instance.  

If that first link doesn't get you what you need, think about the second option.  But either way please create a JIRA!


On Thu, Apr 5, 2018 at 5:49 AM, Martin Nielsen <[hidden email]> wrote:
Right. So i got a little further, and discovered that the problem is the SessionStorageEvaluator on the DefaultSubjectDAO. It is set to a DefaultWebSessionStorageEvaluator, seems like it should handle the problem with this code:

//SHIRO-350: non-web subject instances can't be saved to web-only session managers:
        //since 1.2.1:
        if (!(subject instanceof WebSubject) && (this.sessionManager != null && !(this.sessionManager instanceof NativeSessionManager))) {
            return false;
        }

The problem is that when i login, the DelegatingSubject i create is automatically changed to a WebDelegatingSubject, which means that this code is skipped.

What happens is this:

shiroSubject = subjectBuilder.buildSubject();
Builds a DelegatingSubject, which passes through the Evaluator without issue.

shiroSubject.login(new UsernamePasswordToken(user, password));
Seems to have some unfriendly behavior as the DefaultWebSecurityManager delegates its login to DefaultSecurityManager, which creates a new Subject in its login method which becomes a WebDelegatingSubject thanks to the DefaultWebSubjectFactory set by the  DefaultWebSecurityManager, which also overrides createSubjectContext()  to return a DefaultWebSubjectContext.

In short: It seems no matter what i do, a WebDelegatingSubject is ALWAYS created when i call the login method, causing the  DefaultWebSessionStorageEvaluator to attempt to create a session for a  WebDelegatingSubject which does not have a session as it was created from a normal DelegatingSubject.

This does seem more a bug than by design, and if people shout "bug" i will gladly create a decent bug-report. But for now: How on earth do i get around this?


On Thu, Apr 5, 2018 at 9:23 AM, Martin Nielsen <[hidden email]> wrote:
Hi all

I have an application which uses a WebSecurityManager in conjunction with Apache Wicket. That works all well and good, but now I have encountered a single issue where i need to authenticate a user through a different entrance, which does not have any notion of http sessions. When i try to login a Subject without a session like this:

Subject shiroSubject = null;
Subject.Builder subjectBuilder = new Subject.Builder(manager).sessionCreationEnabled(false);
shiroSubject = subjectBuilder.buildSubject();
...
shiroSubject.login(new UsernamePasswordToken(user, password));

I tried every permutation of sessionCreationEnabled


I get the following exception:


javax.security.auth.login.LoginException: java.lang.IllegalArgumentException: SessionContext must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.createSession(ServletContainerSessionManager.java:103)
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.start(ServletContainerSessionManager.java:64)
at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:152)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:336)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:312)
at org.apache.shiro.mgt.DefaultSubjectDAO.mergePrincipals(DefaultSubjectDAO.java:204)
at org.apache.shiro.mgt.DefaultSubjectDAO.saveToSession(DefaultSubjectDAO.java:166)
at org.apache.shiro.mgt.DefaultSubjectDAO.save(DefaultSubjectDAO.java:147)
at org.apache.shiro.mgt.DefaultSecurityManager.save(DefaultSecurityManager.java:383)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:350)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)

I then looked at WebSubject.Builder i can't create a builder without a Request and Response.


So the question is: When you are using a WebSecurityManager, how do you authenticate a Subject in a case where there is no Request/Response available?

The only way that I can see is to highjack the WebSecurityManager's Authenticator and Authorizer and call their methods directly, completely ignoring the Subject, but that feels so wrong that I am guessing that i am way off :)


Reply | Threaded
Open this post in threaded view
|

Re: Authenticating a Subject without a session with a WebSecurityManager

Brian Demers
Cool, that sounds like something we should be able to write a simple test for too!

On Fri, Apr 6, 2018 at 8:50 AM, Martin Nielsen <[hidden email]> wrote:
Hi Brian

I looked a bit further at the issue and i will create a bug report when i have the chance. The websubject created by the login method ends up having both httpservlet response and requests set to null. That seems to be a pretty straight forward error. I fixed the issue by creating a new websubject factory which creates delegatingsubjects instead of websubjects if the existing subject was itself a delegatingsubject. No second securitymanager needed, at least for now.


On Thu, 5 Apr 2018, 16:22 Brian Demers, <[hidden email]> wrote:
Hey Martin,

Though I agree throwing an exception in this case probably isn't the best default.

I had a similar problem a while back and IIRC I solved it by configuring a second SecurityManager (one configured for web access and the second for non-web).  I had a few other differences configured as well, but this approach means you need to manage the lifecycle of the second instance.  

If that first link doesn't get you what you need, think about the second option.  But either way please create a JIRA!


On Thu, Apr 5, 2018 at 5:49 AM, Martin Nielsen <[hidden email]> wrote:
Right. So i got a little further, and discovered that the problem is the SessionStorageEvaluator on the DefaultSubjectDAO. It is set to a DefaultWebSessionStorageEvaluator, seems like it should handle the problem with this code:

//SHIRO-350: non-web subject instances can't be saved to web-only session managers:
        //since 1.2.1:
        if (!(subject instanceof WebSubject) && (this.sessionManager != null && !(this.sessionManager instanceof NativeSessionManager))) {
            return false;
        }

The problem is that when i login, the DelegatingSubject i create is automatically changed to a WebDelegatingSubject, which means that this code is skipped.

What happens is this:

shiroSubject = subjectBuilder.buildSubject();
Builds a DelegatingSubject, which passes through the Evaluator without issue.

shiroSubject.login(new UsernamePasswordToken(user, password));
Seems to have some unfriendly behavior as the DefaultWebSecurityManager delegates its login to DefaultSecurityManager, which creates a new Subject in its login method which becomes a WebDelegatingSubject thanks to the DefaultWebSubjectFactory set by the  DefaultWebSecurityManager, which also overrides createSubjectContext()  to return a DefaultWebSubjectContext.

In short: It seems no matter what i do, a WebDelegatingSubject is ALWAYS created when i call the login method, causing the  DefaultWebSessionStorageEvaluator to attempt to create a session for a  WebDelegatingSubject which does not have a session as it was created from a normal DelegatingSubject.

This does seem more a bug than by design, and if people shout "bug" i will gladly create a decent bug-report. But for now: How on earth do i get around this?


On Thu, Apr 5, 2018 at 9:23 AM, Martin Nielsen <[hidden email]> wrote:
Hi all

I have an application which uses a WebSecurityManager in conjunction with Apache Wicket. That works all well and good, but now I have encountered a single issue where i need to authenticate a user through a different entrance, which does not have any notion of http sessions. When i try to login a Subject without a session like this:

Subject shiroSubject = null;
Subject.Builder subjectBuilder = new Subject.Builder(manager).sessionCreationEnabled(false);
shiroSubject = subjectBuilder.buildSubject();
...
shiroSubject.login(new UsernamePasswordToken(user, password));

I tried every permutation of sessionCreationEnabled


I get the following exception:


javax.security.auth.login.LoginException: java.lang.IllegalArgumentException: SessionContext must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.createSession(ServletContainerSessionManager.java:103)
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.start(ServletContainerSessionManager.java:64)
at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:152)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:336)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:312)
at org.apache.shiro.mgt.DefaultSubjectDAO.mergePrincipals(DefaultSubjectDAO.java:204)
at org.apache.shiro.mgt.DefaultSubjectDAO.saveToSession(DefaultSubjectDAO.java:166)
at org.apache.shiro.mgt.DefaultSubjectDAO.save(DefaultSubjectDAO.java:147)
at org.apache.shiro.mgt.DefaultSecurityManager.save(DefaultSecurityManager.java:383)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:350)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)

I then looked at WebSubject.Builder i can't create a builder without a Request and Response.


So the question is: When you are using a WebSecurityManager, how do you authenticate a Subject in a case where there is no Request/Response available?

The only way that I can see is to highjack the WebSecurityManager's Authenticator and Authorizer and call their methods directly, completely ignoring the Subject, but that feels so wrong that I am guessing that i am way off :)



Reply | Threaded
Open this post in threaded view
|

Re: Authenticating a Subject without a session with a WebSecurityManager

Martin Nielsen
I created a jira issue SHIRO-646 as well as a pull request https://github.com/apache/shiro/pull/82  

The pull request contains a test and two fixes to make the test pass.

A small note to something I didn't check up on: 
Calling
DefaultWebSecurityManager.setSessionMode(DefaultWebSecurityManager.NATIVE_SESSION_MODE);
makes the error disappear. I can't invest more time in it right now, sorry.

I hope to check up on it in a few days if no one can explain it outright, but trawling though all those classes has been a lengthy, albeit interesting learning experience :)

-Martin

On Fri, Apr 6, 2018 at 3:29 PM, Brian Demers <[hidden email]> wrote:
Cool, that sounds like something we should be able to write a simple test for too!

On Fri, Apr 6, 2018 at 8:50 AM, Martin Nielsen <[hidden email]> wrote:
Hi Brian

I looked a bit further at the issue and i will create a bug report when i have the chance. The websubject created by the login method ends up having both httpservlet response and requests set to null. That seems to be a pretty straight forward error. I fixed the issue by creating a new websubject factory which creates delegatingsubjects instead of websubjects if the existing subject was itself a delegatingsubject. No second securitymanager needed, at least for now.


On Thu, 5 Apr 2018, 16:22 Brian Demers, <[hidden email]> wrote:
Hey Martin,

Though I agree throwing an exception in this case probably isn't the best default.

I had a similar problem a while back and IIRC I solved it by configuring a second SecurityManager (one configured for web access and the second for non-web).  I had a few other differences configured as well, but this approach means you need to manage the lifecycle of the second instance.  

If that first link doesn't get you what you need, think about the second option.  But either way please create a JIRA!


On Thu, Apr 5, 2018 at 5:49 AM, Martin Nielsen <[hidden email]> wrote:
Right. So i got a little further, and discovered that the problem is the SessionStorageEvaluator on the DefaultSubjectDAO. It is set to a DefaultWebSessionStorageEvaluator, seems like it should handle the problem with this code:

//SHIRO-350: non-web subject instances can't be saved to web-only session managers:
        //since 1.2.1:
        if (!(subject instanceof WebSubject) && (this.sessionManager != null && !(this.sessionManager instanceof NativeSessionManager))) {
            return false;
        }

The problem is that when i login, the DelegatingSubject i create is automatically changed to a WebDelegatingSubject, which means that this code is skipped.

What happens is this:

shiroSubject = subjectBuilder.buildSubject();
Builds a DelegatingSubject, which passes through the Evaluator without issue.

shiroSubject.login(new UsernamePasswordToken(user, password));
Seems to have some unfriendly behavior as the DefaultWebSecurityManager delegates its login to DefaultSecurityManager, which creates a new Subject in its login method which becomes a WebDelegatingSubject thanks to the DefaultWebSubjectFactory set by the  DefaultWebSecurityManager, which also overrides createSubjectContext()  to return a DefaultWebSubjectContext.

In short: It seems no matter what i do, a WebDelegatingSubject is ALWAYS created when i call the login method, causing the  DefaultWebSessionStorageEvaluator to attempt to create a session for a  WebDelegatingSubject which does not have a session as it was created from a normal DelegatingSubject.

This does seem more a bug than by design, and if people shout "bug" i will gladly create a decent bug-report. But for now: How on earth do i get around this?


On Thu, Apr 5, 2018 at 9:23 AM, Martin Nielsen <[hidden email]> wrote:
Hi all

I have an application which uses a WebSecurityManager in conjunction with Apache Wicket. That works all well and good, but now I have encountered a single issue where i need to authenticate a user through a different entrance, which does not have any notion of http sessions. When i try to login a Subject without a session like this:

Subject shiroSubject = null;
Subject.Builder subjectBuilder = new Subject.Builder(manager).sessionCreationEnabled(false);
shiroSubject = subjectBuilder.buildSubject();
...
shiroSubject.login(new UsernamePasswordToken(user, password));

I tried every permutation of sessionCreationEnabled


I get the following exception:


javax.security.auth.login.LoginException: java.lang.IllegalArgumentException: SessionContext must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.createSession(ServletContainerSessionManager.java:103)
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.start(ServletContainerSessionManager.java:64)
at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:152)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:336)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:312)
at org.apache.shiro.mgt.DefaultSubjectDAO.mergePrincipals(DefaultSubjectDAO.java:204)
at org.apache.shiro.mgt.DefaultSubjectDAO.saveToSession(DefaultSubjectDAO.java:166)
at org.apache.shiro.mgt.DefaultSubjectDAO.save(DefaultSubjectDAO.java:147)
at org.apache.shiro.mgt.DefaultSecurityManager.save(DefaultSecurityManager.java:383)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:350)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)

I then looked at WebSubject.Builder i can't create a builder without a Request and Response.


So the question is: When you are using a WebSecurityManager, how do you authenticate a Subject in a case where there is no Request/Response available?

The only way that I can see is to highjack the WebSecurityManager's Authenticator and Authorizer and call their methods directly, completely ignoring the Subject, but that feels so wrong that I am guessing that i am way off :)




Reply | Threaded
Open this post in threaded view
|

Re: Authenticating a Subject without a session with a WebSecurityManager

Brian Demers
Thanks!! I left a few minor comments and a pointer to the Apache icla: https://www.apache.org/licenses/icla.pdf

IIRC, the use of NATIVE_SESSION_MODE and/or DefaultWebSessionManager, reverts to the non-web DefaultSessionManager when there is no web context.

On Mon, Apr 9, 2018 at 6:17 AM, Martin Nielsen <[hidden email]> wrote:
I created a jira issue SHIRO-646 as well as a pull request https://github.com/apache/shiro/pull/82  

The pull request contains a test and two fixes to make the test pass.

A small note to something I didn't check up on: 
Calling
DefaultWebSecurityManager.setSessionMode(DefaultWebSecurityManager.NATIVE_SESSION_MODE);
makes the error disappear. I can't invest more time in it right now, sorry.

I hope to check up on it in a few days if no one can explain it outright, but trawling though all those classes has been a lengthy, albeit interesting learning experience :)

-Martin

On Fri, Apr 6, 2018 at 3:29 PM, Brian Demers <[hidden email]> wrote:
Cool, that sounds like something we should be able to write a simple test for too!

On Fri, Apr 6, 2018 at 8:50 AM, Martin Nielsen <[hidden email]> wrote:
Hi Brian

I looked a bit further at the issue and i will create a bug report when i have the chance. The websubject created by the login method ends up having both httpservlet response and requests set to null. That seems to be a pretty straight forward error. I fixed the issue by creating a new websubject factory which creates delegatingsubjects instead of websubjects if the existing subject was itself a delegatingsubject. No second securitymanager needed, at least for now.


On Thu, 5 Apr 2018, 16:22 Brian Demers, <[hidden email]> wrote:
Hey Martin,

Though I agree throwing an exception in this case probably isn't the best default.

I had a similar problem a while back and IIRC I solved it by configuring a second SecurityManager (one configured for web access and the second for non-web).  I had a few other differences configured as well, but this approach means you need to manage the lifecycle of the second instance.  

If that first link doesn't get you what you need, think about the second option.  But either way please create a JIRA!


On Thu, Apr 5, 2018 at 5:49 AM, Martin Nielsen <[hidden email]> wrote:
Right. So i got a little further, and discovered that the problem is the SessionStorageEvaluator on the DefaultSubjectDAO. It is set to a DefaultWebSessionStorageEvaluator, seems like it should handle the problem with this code:

//SHIRO-350: non-web subject instances can't be saved to web-only session managers:
        //since 1.2.1:
        if (!(subject instanceof WebSubject) && (this.sessionManager != null && !(this.sessionManager instanceof NativeSessionManager))) {
            return false;
        }

The problem is that when i login, the DelegatingSubject i create is automatically changed to a WebDelegatingSubject, which means that this code is skipped.

What happens is this:

shiroSubject = subjectBuilder.buildSubject();
Builds a DelegatingSubject, which passes through the Evaluator without issue.

shiroSubject.login(new UsernamePasswordToken(user, password));
Seems to have some unfriendly behavior as the DefaultWebSecurityManager delegates its login to DefaultSecurityManager, which creates a new Subject in its login method which becomes a WebDelegatingSubject thanks to the DefaultWebSubjectFactory set by the  DefaultWebSecurityManager, which also overrides createSubjectContext()  to return a DefaultWebSubjectContext.

In short: It seems no matter what i do, a WebDelegatingSubject is ALWAYS created when i call the login method, causing the  DefaultWebSessionStorageEvaluator to attempt to create a session for a  WebDelegatingSubject which does not have a session as it was created from a normal DelegatingSubject.

This does seem more a bug than by design, and if people shout "bug" i will gladly create a decent bug-report. But for now: How on earth do i get around this?


On Thu, Apr 5, 2018 at 9:23 AM, Martin Nielsen <[hidden email]> wrote:
Hi all

I have an application which uses a WebSecurityManager in conjunction with Apache Wicket. That works all well and good, but now I have encountered a single issue where i need to authenticate a user through a different entrance, which does not have any notion of http sessions. When i try to login a Subject without a session like this:

Subject shiroSubject = null;
Subject.Builder subjectBuilder = new Subject.Builder(manager).sessionCreationEnabled(false);
shiroSubject = subjectBuilder.buildSubject();
...
shiroSubject.login(new UsernamePasswordToken(user, password));

I tried every permutation of sessionCreationEnabled


I get the following exception:


javax.security.auth.login.LoginException: java.lang.IllegalArgumentException: SessionContext must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.createSession(ServletContainerSessionManager.java:103)
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.start(ServletContainerSessionManager.java:64)
at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:152)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:336)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:312)
at org.apache.shiro.mgt.DefaultSubjectDAO.mergePrincipals(DefaultSubjectDAO.java:204)
at org.apache.shiro.mgt.DefaultSubjectDAO.saveToSession(DefaultSubjectDAO.java:166)
at org.apache.shiro.mgt.DefaultSubjectDAO.save(DefaultSubjectDAO.java:147)
at org.apache.shiro.mgt.DefaultSecurityManager.save(DefaultSecurityManager.java:383)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:350)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)

I then looked at WebSubject.Builder i can't create a builder without a Request and Response.


So the question is: When you are using a WebSecurityManager, how do you authenticate a Subject in a case where there is no Request/Response available?

The only way that I can see is to highjack the WebSecurityManager's Authenticator and Authorizer and call their methods directly, completely ignoring the Subject, but that feels so wrong that I am guessing that i am way off :)





Reply | Threaded
Open this post in threaded view
|

Re: Authenticating a Subject without a session with a WebSecurityManager

Martin Nielsen
I mailed the ICLA to  [hidden email] this morning

On Mon, Apr 9, 2018 at 3:50 PM, Brian Demers <[hidden email]> wrote:
Thanks!! I left a few minor comments and a pointer to the Apache icla: https://www.apache.org/licenses/icla.pdf

IIRC, the use of NATIVE_SESSION_MODE and/or DefaultWebSessionManager, reverts to the non-web DefaultSessionManager when there is no web context.

On Mon, Apr 9, 2018 at 6:17 AM, Martin Nielsen <[hidden email]> wrote:
I created a jira issue SHIRO-646 as well as a pull request https://github.com/apache/shiro/pull/82  

The pull request contains a test and two fixes to make the test pass.

A small note to something I didn't check up on: 
Calling
DefaultWebSecurityManager.setSessionMode(DefaultWebSecurityManager.NATIVE_SESSION_MODE);
makes the error disappear. I can't invest more time in it right now, sorry.

I hope to check up on it in a few days if no one can explain it outright, but trawling though all those classes has been a lengthy, albeit interesting learning experience :)

-Martin

On Fri, Apr 6, 2018 at 3:29 PM, Brian Demers <[hidden email]> wrote:
Cool, that sounds like something we should be able to write a simple test for too!

On Fri, Apr 6, 2018 at 8:50 AM, Martin Nielsen <[hidden email]> wrote:
Hi Brian

I looked a bit further at the issue and i will create a bug report when i have the chance. The websubject created by the login method ends up having both httpservlet response and requests set to null. That seems to be a pretty straight forward error. I fixed the issue by creating a new websubject factory which creates delegatingsubjects instead of websubjects if the existing subject was itself a delegatingsubject. No second securitymanager needed, at least for now.


On Thu, 5 Apr 2018, 16:22 Brian Demers, <[hidden email]> wrote:
Hey Martin,

Though I agree throwing an exception in this case probably isn't the best default.

I had a similar problem a while back and IIRC I solved it by configuring a second SecurityManager (one configured for web access and the second for non-web).  I had a few other differences configured as well, but this approach means you need to manage the lifecycle of the second instance.  

If that first link doesn't get you what you need, think about the second option.  But either way please create a JIRA!


On Thu, Apr 5, 2018 at 5:49 AM, Martin Nielsen <[hidden email]> wrote:
Right. So i got a little further, and discovered that the problem is the SessionStorageEvaluator on the DefaultSubjectDAO. It is set to a DefaultWebSessionStorageEvaluator, seems like it should handle the problem with this code:

//SHIRO-350: non-web subject instances can't be saved to web-only session managers:
        //since 1.2.1:
        if (!(subject instanceof WebSubject) && (this.sessionManager != null && !(this.sessionManager instanceof NativeSessionManager))) {
            return false;
        }

The problem is that when i login, the DelegatingSubject i create is automatically changed to a WebDelegatingSubject, which means that this code is skipped.

What happens is this:

shiroSubject = subjectBuilder.buildSubject();
Builds a DelegatingSubject, which passes through the Evaluator without issue.

shiroSubject.login(new UsernamePasswordToken(user, password));
Seems to have some unfriendly behavior as the DefaultWebSecurityManager delegates its login to DefaultSecurityManager, which creates a new Subject in its login method which becomes a WebDelegatingSubject thanks to the DefaultWebSubjectFactory set by the  DefaultWebSecurityManager, which also overrides createSubjectContext()  to return a DefaultWebSubjectContext.

In short: It seems no matter what i do, a WebDelegatingSubject is ALWAYS created when i call the login method, causing the  DefaultWebSessionStorageEvaluator to attempt to create a session for a  WebDelegatingSubject which does not have a session as it was created from a normal DelegatingSubject.

This does seem more a bug than by design, and if people shout "bug" i will gladly create a decent bug-report. But for now: How on earth do i get around this?


On Thu, Apr 5, 2018 at 9:23 AM, Martin Nielsen <[hidden email]> wrote:
Hi all

I have an application which uses a WebSecurityManager in conjunction with Apache Wicket. That works all well and good, but now I have encountered a single issue where i need to authenticate a user through a different entrance, which does not have any notion of http sessions. When i try to login a Subject without a session like this:

Subject shiroSubject = null;
Subject.Builder subjectBuilder = new Subject.Builder(manager).sessionCreationEnabled(false);
shiroSubject = subjectBuilder.buildSubject();
...
shiroSubject.login(new UsernamePasswordToken(user, password));

I tried every permutation of sessionCreationEnabled


I get the following exception:


javax.security.auth.login.LoginException: java.lang.IllegalArgumentException: SessionContext must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.createSession(ServletContainerSessionManager.java:103)
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.start(ServletContainerSessionManager.java:64)
at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:152)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:336)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:312)
at org.apache.shiro.mgt.DefaultSubjectDAO.mergePrincipals(DefaultSubjectDAO.java:204)
at org.apache.shiro.mgt.DefaultSubjectDAO.saveToSession(DefaultSubjectDAO.java:166)
at org.apache.shiro.mgt.DefaultSubjectDAO.save(DefaultSubjectDAO.java:147)
at org.apache.shiro.mgt.DefaultSecurityManager.save(DefaultSecurityManager.java:383)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:350)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)

I then looked at WebSubject.Builder i can't create a builder without a Request and Response.


So the question is: When you are using a WebSecurityManager, how do you authenticate a Subject in a case where there is no Request/Response available?

The only way that I can see is to highjack the WebSecurityManager's Authenticator and Authorizer and call their methods directly, completely ignoring the Subject, but that feels so wrong that I am guessing that i am way off :)






Reply | Threaded
Open this post in threaded view
|

Re: Authenticating a Subject without a session with a WebSecurityManager

Brian Demers
Great!!

On Tue, Apr 10, 2018 at 4:29 AM, Martin Nielsen <[hidden email]> wrote:
I mailed the ICLA to  [hidden email] this morning

On Mon, Apr 9, 2018 at 3:50 PM, Brian Demers <[hidden email]> wrote:
Thanks!! I left a few minor comments and a pointer to the Apache icla: https://www.apache.org/licenses/icla.pdf

IIRC, the use of NATIVE_SESSION_MODE and/or DefaultWebSessionManager, reverts to the non-web DefaultSessionManager when there is no web context.

On Mon, Apr 9, 2018 at 6:17 AM, Martin Nielsen <[hidden email]> wrote:
I created a jira issue SHIRO-646 as well as a pull request https://github.com/apache/shiro/pull/82  

The pull request contains a test and two fixes to make the test pass.

A small note to something I didn't check up on: 
Calling
DefaultWebSecurityManager.setSessionMode(DefaultWebSecurityManager.NATIVE_SESSION_MODE);
makes the error disappear. I can't invest more time in it right now, sorry.

I hope to check up on it in a few days if no one can explain it outright, but trawling though all those classes has been a lengthy, albeit interesting learning experience :)

-Martin

On Fri, Apr 6, 2018 at 3:29 PM, Brian Demers <[hidden email]> wrote:
Cool, that sounds like something we should be able to write a simple test for too!

On Fri, Apr 6, 2018 at 8:50 AM, Martin Nielsen <[hidden email]> wrote:
Hi Brian

I looked a bit further at the issue and i will create a bug report when i have the chance. The websubject created by the login method ends up having both httpservlet response and requests set to null. That seems to be a pretty straight forward error. I fixed the issue by creating a new websubject factory which creates delegatingsubjects instead of websubjects if the existing subject was itself a delegatingsubject. No second securitymanager needed, at least for now.


On Thu, 5 Apr 2018, 16:22 Brian Demers, <[hidden email]> wrote:
Hey Martin,

Though I agree throwing an exception in this case probably isn't the best default.

I had a similar problem a while back and IIRC I solved it by configuring a second SecurityManager (one configured for web access and the second for non-web).  I had a few other differences configured as well, but this approach means you need to manage the lifecycle of the second instance.  

If that first link doesn't get you what you need, think about the second option.  But either way please create a JIRA!


On Thu, Apr 5, 2018 at 5:49 AM, Martin Nielsen <[hidden email]> wrote:
Right. So i got a little further, and discovered that the problem is the SessionStorageEvaluator on the DefaultSubjectDAO. It is set to a DefaultWebSessionStorageEvaluator, seems like it should handle the problem with this code:

//SHIRO-350: non-web subject instances can't be saved to web-only session managers:
        //since 1.2.1:
        if (!(subject instanceof WebSubject) && (this.sessionManager != null && !(this.sessionManager instanceof NativeSessionManager))) {
            return false;
        }

The problem is that when i login, the DelegatingSubject i create is automatically changed to a WebDelegatingSubject, which means that this code is skipped.

What happens is this:

shiroSubject = subjectBuilder.buildSubject();
Builds a DelegatingSubject, which passes through the Evaluator without issue.

shiroSubject.login(new UsernamePasswordToken(user, password));
Seems to have some unfriendly behavior as the DefaultWebSecurityManager delegates its login to DefaultSecurityManager, which creates a new Subject in its login method which becomes a WebDelegatingSubject thanks to the DefaultWebSubjectFactory set by the  DefaultWebSecurityManager, which also overrides createSubjectContext()  to return a DefaultWebSubjectContext.

In short: It seems no matter what i do, a WebDelegatingSubject is ALWAYS created when i call the login method, causing the  DefaultWebSessionStorageEvaluator to attempt to create a session for a  WebDelegatingSubject which does not have a session as it was created from a normal DelegatingSubject.

This does seem more a bug than by design, and if people shout "bug" i will gladly create a decent bug-report. But for now: How on earth do i get around this?


On Thu, Apr 5, 2018 at 9:23 AM, Martin Nielsen <[hidden email]> wrote:
Hi all

I have an application which uses a WebSecurityManager in conjunction with Apache Wicket. That works all well and good, but now I have encountered a single issue where i need to authenticate a user through a different entrance, which does not have any notion of http sessions. When i try to login a Subject without a session like this:

Subject shiroSubject = null;
Subject.Builder subjectBuilder = new Subject.Builder(manager).sessionCreationEnabled(false);
shiroSubject = subjectBuilder.buildSubject();
...
shiroSubject.login(new UsernamePasswordToken(user, password));

I tried every permutation of sessionCreationEnabled


I get the following exception:


javax.security.auth.login.LoginException: java.lang.IllegalArgumentException: SessionContext must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.createSession(ServletContainerSessionManager.java:103)
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.start(ServletContainerSessionManager.java:64)
at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:152)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:336)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:312)
at org.apache.shiro.mgt.DefaultSubjectDAO.mergePrincipals(DefaultSubjectDAO.java:204)
at org.apache.shiro.mgt.DefaultSubjectDAO.saveToSession(DefaultSubjectDAO.java:166)
at org.apache.shiro.mgt.DefaultSubjectDAO.save(DefaultSubjectDAO.java:147)
at org.apache.shiro.mgt.DefaultSecurityManager.save(DefaultSecurityManager.java:383)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:350)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)

I then looked at WebSubject.Builder i can't create a builder without a Request and Response.


So the question is: When you are using a WebSecurityManager, how do you authenticate a Subject in a case where there is no Request/Response available?

The only way that I can see is to highjack the WebSecurityManager's Authenticator and Authorizer and call their methods directly, completely ignoring the Subject, but that feels so wrong that I am guessing that i am way off :)







Reply | Threaded
Open this post in threaded view
|

Re: Authenticating a Subject without a session with a WebSecurityManager

Martin Nielsen
Hi Brian

Are you guys satisfied with the pull request or are you still waiting for something from me?
I just want to be sure i'm not being a bottleneck here :)

-Martin

On Tue, Apr 10, 2018 at 3:52 PM, Brian Demers <[hidden email]> wrote:
Great!!

On Tue, Apr 10, 2018 at 4:29 AM, Martin Nielsen <[hidden email]> wrote:
I mailed the ICLA to  [hidden email] this morning

On Mon, Apr 9, 2018 at 3:50 PM, Brian Demers <[hidden email]> wrote:
Thanks!! I left a few minor comments and a pointer to the Apache icla: https://www.apache.org/licenses/icla.pdf

IIRC, the use of NATIVE_SESSION_MODE and/or DefaultWebSessionManager, reverts to the non-web DefaultSessionManager when there is no web context.

On Mon, Apr 9, 2018 at 6:17 AM, Martin Nielsen <[hidden email]> wrote:
I created a jira issue SHIRO-646 as well as a pull request https://github.com/apache/shiro/pull/82  

The pull request contains a test and two fixes to make the test pass.

A small note to something I didn't check up on: 
Calling
DefaultWebSecurityManager.setSessionMode(DefaultWebSecurityManager.NATIVE_SESSION_MODE);
makes the error disappear. I can't invest more time in it right now, sorry.

I hope to check up on it in a few days if no one can explain it outright, but trawling though all those classes has been a lengthy, albeit interesting learning experience :)

-Martin

On Fri, Apr 6, 2018 at 3:29 PM, Brian Demers <[hidden email]> wrote:
Cool, that sounds like something we should be able to write a simple test for too!

On Fri, Apr 6, 2018 at 8:50 AM, Martin Nielsen <[hidden email]> wrote:
Hi Brian

I looked a bit further at the issue and i will create a bug report when i have the chance. The websubject created by the login method ends up having both httpservlet response and requests set to null. That seems to be a pretty straight forward error. I fixed the issue by creating a new websubject factory which creates delegatingsubjects instead of websubjects if the existing subject was itself a delegatingsubject. No second securitymanager needed, at least for now.


On Thu, 5 Apr 2018, 16:22 Brian Demers, <[hidden email]> wrote:
Hey Martin,

Though I agree throwing an exception in this case probably isn't the best default.

I had a similar problem a while back and IIRC I solved it by configuring a second SecurityManager (one configured for web access and the second for non-web).  I had a few other differences configured as well, but this approach means you need to manage the lifecycle of the second instance.  

If that first link doesn't get you what you need, think about the second option.  But either way please create a JIRA!


On Thu, Apr 5, 2018 at 5:49 AM, Martin Nielsen <[hidden email]> wrote:
Right. So i got a little further, and discovered that the problem is the SessionStorageEvaluator on the DefaultSubjectDAO. It is set to a DefaultWebSessionStorageEvaluator, seems like it should handle the problem with this code:

//SHIRO-350: non-web subject instances can't be saved to web-only session managers:
        //since 1.2.1:
        if (!(subject instanceof WebSubject) && (this.sessionManager != null && !(this.sessionManager instanceof NativeSessionManager))) {
            return false;
        }

The problem is that when i login, the DelegatingSubject i create is automatically changed to a WebDelegatingSubject, which means that this code is skipped.

What happens is this:

shiroSubject = subjectBuilder.buildSubject();
Builds a DelegatingSubject, which passes through the Evaluator without issue.

shiroSubject.login(new UsernamePasswordToken(user, password));
Seems to have some unfriendly behavior as the DefaultWebSecurityManager delegates its login to DefaultSecurityManager, which creates a new Subject in its login method which becomes a WebDelegatingSubject thanks to the DefaultWebSubjectFactory set by the  DefaultWebSecurityManager, which also overrides createSubjectContext()  to return a DefaultWebSubjectContext.

In short: It seems no matter what i do, a WebDelegatingSubject is ALWAYS created when i call the login method, causing the  DefaultWebSessionStorageEvaluator to attempt to create a session for a  WebDelegatingSubject which does not have a session as it was created from a normal DelegatingSubject.

This does seem more a bug than by design, and if people shout "bug" i will gladly create a decent bug-report. But for now: How on earth do i get around this?


On Thu, Apr 5, 2018 at 9:23 AM, Martin Nielsen <[hidden email]> wrote:
Hi all

I have an application which uses a WebSecurityManager in conjunction with Apache Wicket. That works all well and good, but now I have encountered a single issue where i need to authenticate a user through a different entrance, which does not have any notion of http sessions. When i try to login a Subject without a session like this:

Subject shiroSubject = null;
Subject.Builder subjectBuilder = new Subject.Builder(manager).sessionCreationEnabled(false);
shiroSubject = subjectBuilder.buildSubject();
...
shiroSubject.login(new UsernamePasswordToken(user, password));

I tried every permutation of sessionCreationEnabled


I get the following exception:


javax.security.auth.login.LoginException: java.lang.IllegalArgumentException: SessionContext must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.createSession(ServletContainerSessionManager.java:103)
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.start(ServletContainerSessionManager.java:64)
at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:152)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:336)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:312)
at org.apache.shiro.mgt.DefaultSubjectDAO.mergePrincipals(DefaultSubjectDAO.java:204)
at org.apache.shiro.mgt.DefaultSubjectDAO.saveToSession(DefaultSubjectDAO.java:166)
at org.apache.shiro.mgt.DefaultSubjectDAO.save(DefaultSubjectDAO.java:147)
at org.apache.shiro.mgt.DefaultSecurityManager.save(DefaultSecurityManager.java:383)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:350)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)

I then looked at WebSubject.Builder i can't create a builder without a Request and Response.


So the question is: When you are using a WebSecurityManager, how do you authenticate a Subject in a case where there is no Request/Response available?

The only way that I can see is to highjack the WebSecurityManager's Authenticator and Authorizer and call their methods directly, completely ignoring the Subject, but that feels so wrong that I am guessing that i am way off :)








Reply | Threaded
Open this post in threaded view
|

Re: Authenticating a Subject without a session with a WebSecurityManager

Brian Demers
Sorry for the delay, (I should have taken care of this sooner)

I'll get it merged this week, unless someone else gets to it first!

On Thu, Apr 26, 2018 at 5:03 AM, Martin Nielsen <[hidden email]> wrote:
Hi Brian

Are you guys satisfied with the pull request or are you still waiting for something from me?
I just want to be sure i'm not being a bottleneck here :)

-Martin

On Tue, Apr 10, 2018 at 3:52 PM, Brian Demers <[hidden email]> wrote:
Great!!

On Tue, Apr 10, 2018 at 4:29 AM, Martin Nielsen <[hidden email]> wrote:
I mailed the ICLA to  [hidden email] this morning

On Mon, Apr 9, 2018 at 3:50 PM, Brian Demers <[hidden email]> wrote:
Thanks!! I left a few minor comments and a pointer to the Apache icla: https://www.apache.org/licenses/icla.pdf

IIRC, the use of NATIVE_SESSION_MODE and/or DefaultWebSessionManager, reverts to the non-web DefaultSessionManager when there is no web context.

On Mon, Apr 9, 2018 at 6:17 AM, Martin Nielsen <[hidden email]> wrote:
I created a jira issue SHIRO-646 as well as a pull request https://github.com/apache/shiro/pull/82  

The pull request contains a test and two fixes to make the test pass.

A small note to something I didn't check up on: 
Calling
DefaultWebSecurityManager.setSessionMode(DefaultWebSecurityManager.NATIVE_SESSION_MODE);
makes the error disappear. I can't invest more time in it right now, sorry.

I hope to check up on it in a few days if no one can explain it outright, but trawling though all those classes has been a lengthy, albeit interesting learning experience :)

-Martin

On Fri, Apr 6, 2018 at 3:29 PM, Brian Demers <[hidden email]> wrote:
Cool, that sounds like something we should be able to write a simple test for too!

On Fri, Apr 6, 2018 at 8:50 AM, Martin Nielsen <[hidden email]> wrote:
Hi Brian

I looked a bit further at the issue and i will create a bug report when i have the chance. The websubject created by the login method ends up having both httpservlet response and requests set to null. That seems to be a pretty straight forward error. I fixed the issue by creating a new websubject factory which creates delegatingsubjects instead of websubjects if the existing subject was itself a delegatingsubject. No second securitymanager needed, at least for now.


On Thu, 5 Apr 2018, 16:22 Brian Demers, <[hidden email]> wrote:
Hey Martin,

Though I agree throwing an exception in this case probably isn't the best default.

I had a similar problem a while back and IIRC I solved it by configuring a second SecurityManager (one configured for web access and the second for non-web).  I had a few other differences configured as well, but this approach means you need to manage the lifecycle of the second instance.  

If that first link doesn't get you what you need, think about the second option.  But either way please create a JIRA!


On Thu, Apr 5, 2018 at 5:49 AM, Martin Nielsen <[hidden email]> wrote:
Right. So i got a little further, and discovered that the problem is the SessionStorageEvaluator on the DefaultSubjectDAO. It is set to a DefaultWebSessionStorageEvaluator, seems like it should handle the problem with this code:

//SHIRO-350: non-web subject instances can't be saved to web-only session managers:
        //since 1.2.1:
        if (!(subject instanceof WebSubject) && (this.sessionManager != null && !(this.sessionManager instanceof NativeSessionManager))) {
            return false;
        }

The problem is that when i login, the DelegatingSubject i create is automatically changed to a WebDelegatingSubject, which means that this code is skipped.

What happens is this:

shiroSubject = subjectBuilder.buildSubject();
Builds a DelegatingSubject, which passes through the Evaluator without issue.

shiroSubject.login(new UsernamePasswordToken(user, password));
Seems to have some unfriendly behavior as the DefaultWebSecurityManager delegates its login to DefaultSecurityManager, which creates a new Subject in its login method which becomes a WebDelegatingSubject thanks to the DefaultWebSubjectFactory set by the  DefaultWebSecurityManager, which also overrides createSubjectContext()  to return a DefaultWebSubjectContext.

In short: It seems no matter what i do, a WebDelegatingSubject is ALWAYS created when i call the login method, causing the  DefaultWebSessionStorageEvaluator to attempt to create a session for a  WebDelegatingSubject which does not have a session as it was created from a normal DelegatingSubject.

This does seem more a bug than by design, and if people shout "bug" i will gladly create a decent bug-report. But for now: How on earth do i get around this?


On Thu, Apr 5, 2018 at 9:23 AM, Martin Nielsen <[hidden email]> wrote:
Hi all

I have an application which uses a WebSecurityManager in conjunction with Apache Wicket. That works all well and good, but now I have encountered a single issue where i need to authenticate a user through a different entrance, which does not have any notion of http sessions. When i try to login a Subject without a session like this:

Subject shiroSubject = null;
Subject.Builder subjectBuilder = new Subject.Builder(manager).sessionCreationEnabled(false);
shiroSubject = subjectBuilder.buildSubject();
...
shiroSubject.login(new UsernamePasswordToken(user, password));

I tried every permutation of sessionCreationEnabled


I get the following exception:


javax.security.auth.login.LoginException: java.lang.IllegalArgumentException: SessionContext must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.createSession(ServletContainerSessionManager.java:103)
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.start(ServletContainerSessionManager.java:64)
at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:152)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:336)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:312)
at org.apache.shiro.mgt.DefaultSubjectDAO.mergePrincipals(DefaultSubjectDAO.java:204)
at org.apache.shiro.mgt.DefaultSubjectDAO.saveToSession(DefaultSubjectDAO.java:166)
at org.apache.shiro.mgt.DefaultSubjectDAO.save(DefaultSubjectDAO.java:147)
at org.apache.shiro.mgt.DefaultSecurityManager.save(DefaultSecurityManager.java:383)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:350)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)

I then looked at WebSubject.Builder i can't create a builder without a Request and Response.


So the question is: When you are using a WebSecurityManager, how do you authenticate a Subject in a case where there is no Request/Response available?

The only way that I can see is to highjack the WebSecurityManager's Authenticator and Authorizer and call their methods directly, completely ignoring the Subject, but that feels so wrong that I am guessing that i am way off :)









Reply | Threaded
Open this post in threaded view
|

Re: Authenticating a Subject without a session with a WebSecurityManager

Martin Nielsen
No problem. I just wanted to make sure you weren't waiting for me to do something.

On Thu, Apr 26, 2018 at 4:24 PM, Brian Demers <[hidden email]> wrote:
Sorry for the delay, (I should have taken care of this sooner)

I'll get it merged this week, unless someone else gets to it first!

On Thu, Apr 26, 2018 at 5:03 AM, Martin Nielsen <[hidden email]> wrote:
Hi Brian

Are you guys satisfied with the pull request or are you still waiting for something from me?
I just want to be sure i'm not being a bottleneck here :)

-Martin

On Tue, Apr 10, 2018 at 3:52 PM, Brian Demers <[hidden email]> wrote:
Great!!

On Tue, Apr 10, 2018 at 4:29 AM, Martin Nielsen <[hidden email]> wrote:
I mailed the ICLA to  [hidden email] this morning

On Mon, Apr 9, 2018 at 3:50 PM, Brian Demers <[hidden email]> wrote:
Thanks!! I left a few minor comments and a pointer to the Apache icla: https://www.apache.org/licenses/icla.pdf

IIRC, the use of NATIVE_SESSION_MODE and/or DefaultWebSessionManager, reverts to the non-web DefaultSessionManager when there is no web context.

On Mon, Apr 9, 2018 at 6:17 AM, Martin Nielsen <[hidden email]> wrote:
I created a jira issue SHIRO-646 as well as a pull request https://github.com/apache/shiro/pull/82  

The pull request contains a test and two fixes to make the test pass.

A small note to something I didn't check up on: 
Calling
DefaultWebSecurityManager.setSessionMode(DefaultWebSecurityManager.NATIVE_SESSION_MODE);
makes the error disappear. I can't invest more time in it right now, sorry.

I hope to check up on it in a few days if no one can explain it outright, but trawling though all those classes has been a lengthy, albeit interesting learning experience :)

-Martin

On Fri, Apr 6, 2018 at 3:29 PM, Brian Demers <[hidden email]> wrote:
Cool, that sounds like something we should be able to write a simple test for too!

On Fri, Apr 6, 2018 at 8:50 AM, Martin Nielsen <[hidden email]> wrote:
Hi Brian

I looked a bit further at the issue and i will create a bug report when i have the chance. The websubject created by the login method ends up having both httpservlet response and requests set to null. That seems to be a pretty straight forward error. I fixed the issue by creating a new websubject factory which creates delegatingsubjects instead of websubjects if the existing subject was itself a delegatingsubject. No second securitymanager needed, at least for now.


On Thu, 5 Apr 2018, 16:22 Brian Demers, <[hidden email]> wrote:
Hey Martin,

Though I agree throwing an exception in this case probably isn't the best default.

I had a similar problem a while back and IIRC I solved it by configuring a second SecurityManager (one configured for web access and the second for non-web).  I had a few other differences configured as well, but this approach means you need to manage the lifecycle of the second instance.  

If that first link doesn't get you what you need, think about the second option.  But either way please create a JIRA!


On Thu, Apr 5, 2018 at 5:49 AM, Martin Nielsen <[hidden email]> wrote:
Right. So i got a little further, and discovered that the problem is the SessionStorageEvaluator on the DefaultSubjectDAO. It is set to a DefaultWebSessionStorageEvaluator, seems like it should handle the problem with this code:

//SHIRO-350: non-web subject instances can't be saved to web-only session managers:
        //since 1.2.1:
        if (!(subject instanceof WebSubject) && (this.sessionManager != null && !(this.sessionManager instanceof NativeSessionManager))) {
            return false;
        }

The problem is that when i login, the DelegatingSubject i create is automatically changed to a WebDelegatingSubject, which means that this code is skipped.

What happens is this:

shiroSubject = subjectBuilder.buildSubject();
Builds a DelegatingSubject, which passes through the Evaluator without issue.

shiroSubject.login(new UsernamePasswordToken(user, password));
Seems to have some unfriendly behavior as the DefaultWebSecurityManager delegates its login to DefaultSecurityManager, which creates a new Subject in its login method which becomes a WebDelegatingSubject thanks to the DefaultWebSubjectFactory set by the  DefaultWebSecurityManager, which also overrides createSubjectContext()  to return a DefaultWebSubjectContext.

In short: It seems no matter what i do, a WebDelegatingSubject is ALWAYS created when i call the login method, causing the  DefaultWebSessionStorageEvaluator to attempt to create a session for a  WebDelegatingSubject which does not have a session as it was created from a normal DelegatingSubject.

This does seem more a bug than by design, and if people shout "bug" i will gladly create a decent bug-report. But for now: How on earth do i get around this?


On Thu, Apr 5, 2018 at 9:23 AM, Martin Nielsen <[hidden email]> wrote:
Hi all

I have an application which uses a WebSecurityManager in conjunction with Apache Wicket. That works all well and good, but now I have encountered a single issue where i need to authenticate a user through a different entrance, which does not have any notion of http sessions. When i try to login a Subject without a session like this:

Subject shiroSubject = null;
Subject.Builder subjectBuilder = new Subject.Builder(manager).sessionCreationEnabled(false);
shiroSubject = subjectBuilder.buildSubject();
...
shiroSubject.login(new UsernamePasswordToken(user, password));

I tried every permutation of sessionCreationEnabled


I get the following exception:


javax.security.auth.login.LoginException: java.lang.IllegalArgumentException: SessionContext must be an HTTP compatible implementation.
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.createSession(ServletContainerSessionManager.java:103)
at org.apache.shiro.web.session.mgt.ServletContainerSessionManager.start(ServletContainerSessionManager.java:64)
at org.apache.shiro.mgt.SessionsSecurityManager.start(SessionsSecurityManager.java:152)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:336)
at org.apache.shiro.subject.support.DelegatingSubject.getSession(DelegatingSubject.java:312)
at org.apache.shiro.mgt.DefaultSubjectDAO.mergePrincipals(DefaultSubjectDAO.java:204)
at org.apache.shiro.mgt.DefaultSubjectDAO.saveToSession(DefaultSubjectDAO.java:166)
at org.apache.shiro.mgt.DefaultSubjectDAO.save(DefaultSubjectDAO.java:147)
at org.apache.shiro.mgt.DefaultSecurityManager.save(DefaultSecurityManager.java:383)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:350)
at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)

I then looked at WebSubject.Builder i can't create a builder without a Request and Response.


So the question is: When you are using a WebSecurityManager, how do you authenticate a Subject in a case where there is no Request/Response available?

The only way that I can see is to highjack the WebSecurityManager's Authenticator and Authorizer and call their methods directly, completely ignoring the Subject, but that feels so wrong that I am guessing that i am way off :)