You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Jerry Malcolm <te...@malcolms.com> on 2023/11/05 00:17:46 UTC

Admin password for Tomcat

My support team needs to be able to log in to our site as various users 
(on behalf of...) to be able to see exactly what they are seeing since 
roles, access groups, history is different for different users.  I would 
like to implement an admin password where I can log in as any userId 
with this password.  I totally realize the security risks involved in 
this.  But I am handling the security risks with additional 
authorizations.  I simply need to make every user have two passwords... 
their real personal password, and the admin password.  The only 
alternative I have right now is to save off the user's password hash in 
the USERS table, replace it with my password hash, then restore the 
user's original password when I'm done.  I'm not thrilled with that 
solution first because it's a pain and error prone, and also because the 
user can no longer log in while their password is replaced with my password.

  I figure this function is buried in the authenticator code somewhere.  
But I'd first like to see if anybody has done anything like this 
already.  If not, could somebody point me in the right direction to the 
tomcat source file that I'm going to need to modify and also what's 
involved in making authentication use my updated class instead of the 
default.

Suggestions?

Thx

Jerry


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Admin password for Tomcat

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Jerry,

On 12/30/23 01:20, Jerry Malcolm wrote:
> Chris,
> 
> On 12/29/2023 11:22 AM, Christopher Schultz wrote:
>> Jerry,
>>
>> On 12/28/23 18:33, Jerry Malcolm wrote:
>>> Chris,
>>>
>>> On 12/28/2023 3:38 PM, Christopher Schultz wrote:
>>>> Jerry.
>>>>
>>>> On 12/27/23 02:13, Jerry Malcolm wrote:
>>>>> I implemented the filter as you suggested.  But I guess I'm going 
>>>>> to need some education on sessions.  Down in a user profile web 
>>>>> page I have a button to "Impersonate".
>>>>
>>>> I'm with you so far.
>>>>
>>>>> I create the GenericPrincipal object and store it in the session. 
>>>>> I've checked several times, and every time I come back to that 
>>>>> code, the attribute is set in the session object.
>>>>
>>>> Good. When you do that, do you remove the "real" user's 
>>>> GenericPrincipal object from the session? Or are they both in there?
>> >
>>> Sorry... lost you on that one.  I am just setting a custom  > 
>>> "GenericPrincipal" attribute named "impersonatedPrincipal" in the
>>> session when a user clicks the "Impersonate" button on the web page.
>>
>> This answers my question. I was wondering if you do this:
>>
>> session.setAttribute("user", impersonatedUser); // Replace
>>
>> or this:
>>
>> session.setAttribut("impersonatedUser", impersonatedUser);
>>
>> And it seems you are doing the second one.
>>
>>> In my understanding, at this point I'm just 'telling' the session
>>> that on subsequent requests in the custom filter, here's a principal
>>> object that I want to insert.
>> As long as your code agrees with you :)
>>
>>> I also noted in your early example that you stored a 'User' class as 
>>> the attribute in the session, not a GenericPrincipal.  I couldn't 
>>> find a "User" class.  So I just used GenericPrincipal, since that was 
>>> what I will insert in the request object in the filter.
>>
>> We use User in our session, and essentially wrap it in a 
>> GenericPrincipal when necessary. We are playing a lot of games, here, 
>> in our code, so I apologize if we go down this road and it's a lot 
>> longer than you had expected...
>>
>>>> Remember that if Tomcat is going to enforce your authentication and 
>>>> authorization constraints, your Filter will run after that, and 
>>>> Tomcat and your application will disagree over which user is 
>>>> currently logged-in.
>> >
>>> I'm not removing the real principal from anything.  Not sure how to 
>>> do that?  in HttpSession?  in HttpRequest?  I assumed returning my 
>>> new GenericPrincipal in the RequestFacade would override any other 
>>> code asking for the principal.
>>
>> It will... unless that code runs before your Filter has a chance to 
>> pull the wool over the application's eyes. For example... Tomcat's 
>> authentication and authorization code will run in a Valve, which runs 
>> before all Filters.
>>
>>> How do I go about removing the real principal?
>>
>> Let's save that for later ;)
>>
>>>>> But when I put breakpoint in my new Filter object and look in the
>>>>> session, no attribute.  It's a different session object from what I
>>>>> can tell.
>>>> That's weird.
>>>>
>>>> When you say "every time I come back to that code, the attribute is 
>>>> set in the session" ... what code are you taking about?
>> >
>>> The filter's 'version' of the session doesn't have the 
>>> "impersonatedPrincipal" attribute set (it doesn't have any attributes 
>>> set).  But after clicking Impersonate, hitting the breakpoint, and 
>>> watching the session attribute get set, I hit F5 to refresh the page. 
>>> The filter breakpoint again doesn't have the attribute.  But if I 
>>> click "Impersonate" again and hit that breakpoint the 
>>> "impersonatedPrincipal" session attribute exists in the session.
>>
>> Is the session identifier changing?
>>
>>>>> I really thought I understood session objects.  I thought there was 
>>>>> only one session object throughout the processing of a servlet.
>>>>
>>>> Yes, if s/servlet/request/.
>>>>
>>>>> But I'm obviously missing something in the flows.  Why is there a
>>>>> different session object in the filter than in the main body of the
>>>>> servlet?  I did the getSession(false) as you suggested.  The session
>>>>> object is not null.  It just doesn't have the attribute set. Yet if
>>>>> I hit the Impersonate button again and hit the breakpoint, the
>>>>> GenericPrincipal attribute is sitting in the session just as I placed
>>>>> it earlier.
>>>> If the difference between when Tomcat evaluates e.g. user-roles 
>>>> versus when your application does won't explain what's happening, we 
>>>> might need to see some code.
>>>
>>> Code:
>>>
>>> Other than a loop that builds a Roles vector, these are the two lines 
>>> that create the session attribute when the "Impersonate" button is 
>>> clicked.
>>>
>>> GenericPrincipal newPrincipal = new GenericPrincipal( getUserName(),
>>> getPassword(),
>>> roles );
>>>        getCtrl().getRequest().getSession(false).setAttribute( 
>>> "impersonatedPrincipal", newPrincipal );
>>
>> Hmm. What are Ctrl and Request that you are "getting"? Usually, both 
>> the servlet and the Filter see objects passed to them directly in the 
>> doFilter() and service()/doGet/doPost/whatever methods in the servlet.
>>
>>> And this is the filter:
>>>
>>>        PrintWriter out = response.getWriter();
>>>
>>>        HttpSession session = 
>>> ((HttpServletRequest)request).getSession(false);
>>>        if(session != null)
>>>        {
>>>           final GenericPrincipal impersonatedPrincipal = 
>>> (GenericPrincipal) session.getAttribute("impersonatedPrincipal");
>>>           if (impersonatedPrincipal != null)
>>>           {
>>>              System.out.println( "Impersonating");
>>>              request = new 
>>> HttpServletRequestWrapper((HttpServletRequest)request)
>>>              {
>>>                 public Principal getUserPrincipal()
>>>                 {
>>>                    return impersonatedPrincipal;
>>>                 }
>>>              };
>>>           }
>>>        }
>>>        chain.doFilter(request, response);
>>>
>>> I feel like I'm right on top of the solution.  But I just can't seem 
>>> to get over the finish line. Thanks for you help.
>>
>> Filter looks good. The other code looks sus.
>>
>> -chris
>>
> The saga continues... the Ctrl object is simply a briefcase object that 
> stores the request object and a bunch of other objects that my model 
> code needs .  The request is passed in on the Ctrl class constructor. So 
> it is definitely the same request (and therefore the same session) that 
> comes in on the doGet/doPost method on the servlet.
> 
> I added a println of the session id in the filter and in the code that 
> sets the Principal object in the session.  I'm beginning to see the 
> problem.  I have quite a few web apps running in this host.  I realize 
> now that each one has its own session.  I'm surprised that the session 
> id that sets the attribute doesn't match any of the other sessions.  But 
> I realize that at best this is not going to work correctly unless I set 
> the impersonatedPrinicipal object in every session in the host.  I use 
> SingleSignon.  But SingleSignon won't propagate a custom session 
> attribute to all of the other sessions in the host, will it?

Nope. Single sign-in just propagates authentication information across 
the web applications. They definitely do not share sessions.

> Because I wanted the filter to work on all web apps, I added the filter 
> definition to the /conf/web.xml instead of in every web app's web.xml. 
> Does the global web.xml file have a separate session from all of the 
> other web app sessions?

Yep. Setting the filter in conf/web.xml has the effect of separately 
configuring it by default for all applications, but they aren't shared 
in any way.

> If I understand what should happen here, the sole purpose of the session 
> object attribute is to keep track of an impersontated GenericPrincipal 
> object that I want to use, and to tell the filter to set this as the 
> Principal for this request if the attribute exists.  It's beginning to 
> seem like the session object(s) may not be the best place to store the 
> Principal object for the filter to use, given all of the instances of 
> session.

Probably not. I think maybe this whole approach is not going to work. I 
didn't realize you had multiple applications in play. This will probably 
require a different strategy. :/

> As a possible alternative, I figure it might introduce 
> additional security risks, but would it be possible to serialize the 
> impersonatedPrincipal object and pass it back and forth as a cookie? The 
> filter would check for the cookie and deserialize it and install it as 
> the UserPrincipal the same way I was trying to do it by storing it in 
> the session.  At least a session cookie would come to all web apps, 
> correct?  Is there a better place to store the impersonatedPrincipal 
> that would be easily accessible to all webapps?

I wouldn't use GenericPrincipal. I wouldn't use serialization. And I 
wouldn't use a Cookie. Instead, I might look at something like JWT (JSON 
Web Token) as a way to pass authentication information from one 
application to another one. I suppose you could do it via a cookie if 
you need it to follow you around through all the various web applications.

This will probably require you to write a custom authentication module 
for Tomcat. You could subclass an existing authentication module such as 
FormAuthenticator and have it look for a custom cookie containing 
authentication information, and fall back to the superclass's behavior 
of asking for a form-based login.

The reason I suggest JWT is because the technology exists, you can 
easily get Java libraries for it, and it's as secure as you are willing 
to make it. Basically, you take some name/value pairs, shove them into a 
map, sign it, and you get a JWT. The recipient verifies the signature 
using a trusted certificate (you can do it other ways, but this is best 
IMHO) and does whatever is appropriate -- such as setting the Principal 
on the request/session/whatever.

> Here is the list of sessionIds from just bringing up the home page and 
> the page to set the impersonatedPrincipal attribute.  About halfway 
> down, you'll see the sessionId that I actually stored the 
> impersonatedPrincipal in.
> 
> ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
> ImpersonateFilter: FFB83D207968FBF944D36E86F50A8871
> ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
> ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
> ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
> ImpersonateFilter: 20121D0DA12AC42E95F0567820D925EA
> ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
> ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
> ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
> ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
> ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
> ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
> ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
> ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
> ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
> ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
> ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
> ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
> ImpersonateFilter: FFB83D207968FBF944D36E86F50A8871
> ImpersonateFilter: FFB83D207968FBF944D36E86F50A8871
> ImpersonateFilter: FFB83D207968FBF944D36E86F50A8871
> ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
> ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
> Set session attribute: E6412E5B6419E06D5233F53D40D88E9E
> ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
> ImpersonateFilter: 640691F73EB2139A1BA88E47D2FB189F
> ImpersonateFilter: 640691F73EB2139A1BA88E47D2FB189F
> ImpersonateFilter: 640691F73EB2139A1BA88E47D2FB189F
> ImpersonateFilter: 20121D0DA12AC42E95F0567820D925EA
> ImpersonateFilter: 640691F73EB2139A1BA88E47D2FB189F
> ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
> ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
> ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A

That's ... a lot of applications.

I think a custom authenticator is going to be your best bet.

How does your application authenticate users primarily?

-chris

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Admin password for Tomcat

Posted by Jerry Malcolm <te...@malcolms.com>.
Chris,

On 12/29/2023 11:22 AM, Christopher Schultz wrote:
> Jerry,
>
> On 12/28/23 18:33, Jerry Malcolm wrote:
>> Chris,
>>
>> On 12/28/2023 3:38 PM, Christopher Schultz wrote:
>>> Jerry.
>>>
>>> On 12/27/23 02:13, Jerry Malcolm wrote:
>>>> I implemented the filter as you suggested.  But I guess I'm going 
>>>> to need some education on sessions.  Down in a user profile web 
>>>> page I have a button to "Impersonate".
>>>
>>> I'm with you so far.
>>>
>>>> I create the GenericPrincipal object and store it in the session. 
>>>> I've checked several times, and every time I come back to that 
>>>> code, the attribute is set in the session object.
>>>
>>> Good. When you do that, do you remove the "real" user's 
>>> GenericPrincipal object from the session? Or are they both in there?
> >
>> Sorry... lost you on that one.  I am just setting a custom  > 
>> "GenericPrincipal" attribute named "impersonatedPrincipal" in the
>> session when a user clicks the "Impersonate" button on the web page.
>
> This answers my question. I was wondering if you do this:
>
> session.setAttribute("user", impersonatedUser); // Replace
>
> or this:
>
> session.setAttribut("impersonatedUser", impersonatedUser);
>
> And it seems you are doing the second one.
>
>> In my understanding, at this point I'm just 'telling' the session
>> that on subsequent requests in the custom filter, here's a principal
>> object that I want to insert.
> As long as your code agrees with you :)
>
>> I also noted in your early example that you stored a 'User' class as 
>> the attribute in the session, not a GenericPrincipal.  I couldn't 
>> find a "User" class.  So I just used GenericPrincipal, since that was 
>> what I will insert in the request object in the filter.
>
> We use User in our session, and essentially wrap it in a 
> GenericPrincipal when necessary. We are playing a lot of games, here, 
> in our code, so I apologize if we go down this road and it's a lot 
> longer than you had expected...
>
>>> Remember that if Tomcat is going to enforce your authentication and 
>>> authorization constraints, your Filter will run after that, and 
>>> Tomcat and your application will disagree over which user is 
>>> currently logged-in.
> >
>> I'm not removing the real principal from anything.  Not sure how to 
>> do that?  in HttpSession?  in HttpRequest?  I assumed returning my 
>> new GenericPrincipal in the RequestFacade would override any other 
>> code asking for the principal.
>
> It will... unless that code runs before your Filter has a chance to 
> pull the wool over the application's eyes. For example... Tomcat's 
> authentication and authorization code will run in a Valve, which runs 
> before all Filters.
>
>> How do I go about removing the real principal?
>
> Let's save that for later ;)
>
>>>> But when I put breakpoint in my new Filter object and look in the
>>>> session, no attribute.  It's a different session object from what I
>>>> can tell.
>>> That's weird.
>>>
>>> When you say "every time I come back to that code, the attribute is 
>>> set in the session" ... what code are you taking about?
> >
>> The filter's 'version' of the session doesn't have the 
>> "impersonatedPrincipal" attribute set (it doesn't have any attributes 
>> set).  But after clicking Impersonate, hitting the breakpoint, and 
>> watching the session attribute get set, I hit F5 to refresh the page. 
>> The filter breakpoint again doesn't have the attribute.  But if I 
>> click "Impersonate" again and hit that breakpoint the 
>> "impersonatedPrincipal" session attribute exists in the session.
>
> Is the session identifier changing?
>
>>>> I really thought I understood session objects.  I thought there was 
>>>> only one session object throughout the processing of a servlet.
>>>
>>> Yes, if s/servlet/request/.
>>>
>>>> But I'm obviously missing something in the flows.  Why is there a
>>>> different session object in the filter than in the main body of the
>>>> servlet?  I did the getSession(false) as you suggested.  The session
>>>> object is not null.  It just doesn't have the attribute set. Yet if
>>>> I hit the Impersonate button again and hit the breakpoint, the
>>>> GenericPrincipal attribute is sitting in the session just as I placed
>>>> it earlier.
>>> If the difference between when Tomcat evaluates e.g. user-roles 
>>> versus when your application does won't explain what's happening, we 
>>> might need to see some code.
>>
>> Code:
>>
>> Other than a loop that builds a Roles vector, these are the two lines 
>> that create the session attribute when the "Impersonate" button is 
>> clicked.
>>
>> GenericPrincipal newPrincipal = new GenericPrincipal( getUserName(),
>> getPassword(),
>> roles );
>>        getCtrl().getRequest().getSession(false).setAttribute( 
>> "impersonatedPrincipal", newPrincipal );
>
> Hmm. What are Ctrl and Request that you are "getting"? Usually, both 
> the servlet and the Filter see objects passed to them directly in the 
> doFilter() and service()/doGet/doPost/whatever methods in the servlet.
>
>> And this is the filter:
>>
>>        PrintWriter out = response.getWriter();
>>
>>        HttpSession session = 
>> ((HttpServletRequest)request).getSession(false);
>>        if(session != null)
>>        {
>>           final GenericPrincipal impersonatedPrincipal = 
>> (GenericPrincipal) session.getAttribute("impersonatedPrincipal");
>>           if (impersonatedPrincipal != null)
>>           {
>>              System.out.println( "Impersonating");
>>              request = new 
>> HttpServletRequestWrapper((HttpServletRequest)request)
>>              {
>>                 public Principal getUserPrincipal()
>>                 {
>>                    return impersonatedPrincipal;
>>                 }
>>              };
>>           }
>>        }
>>        chain.doFilter(request, response);
>>
>> I feel like I'm right on top of the solution.  But I just can't seem 
>> to get over the finish line. Thanks for you help.
>
> Filter looks good. The other code looks sus.
>
> -chris
>
The saga continues... the Ctrl object is simply a briefcase object that 
stores the request object and a bunch of other objects that my model 
code needs .  The request is passed in on the Ctrl class constructor.  
So it is definitely the same request (and therefore the same session) 
that comes in on the doGet/doPost method on the servlet.

I added a println of the session id in the filter and in the code that 
sets the Principal object in the session.  I'm beginning to see the 
problem.  I have quite a few web apps running in this host.  I realize 
now that each one has its own session.  I'm surprised that the session 
id that sets the attribute doesn't match any of the other sessions.  But 
I realize that at best this is not going to work correctly unless I set 
the impersonatedPrinicipal object in every session in the host.  I use 
SingleSignon.  But SingleSignon won't propagate a custom session 
attribute to all of the other sessions in the host, will it?

Because I wanted the filter to work on all web apps, I added the filter 
definition to the /conf/web.xml instead of in every web app's web.xml.   
Does the global web.xml file have a separate session from all of the 
other web app sessions?

If I understand what should happen here, the sole purpose of the session 
object attribute is to keep track of an impersontated GenericPrincipal 
object that I want to use, and to tell the filter to set this as the 
Principal for this request if the attribute exists.  It's beginning to 
seem like the session object(s) may not be the best place to store the 
Principal object for the filter to use, given all of the instances of 
session.   As a possible alternative, I figure it might introduce 
additional security risks, but would it be possible to serialize the 
impersonatedPrincipal object and pass it back and forth as a cookie?  
The filter would check for the cookie and deserialize it and install it 
as the UserPrincipal the same way I was trying to do it by storing it in 
the session.  At least a session cookie would come to all web apps, 
correct?  Is there a better place to store the impersonatedPrincipal  
that would be easily accessible to all webapps?

Here is the list of sessionIds from just bringing up the home page and 
the page to set the impersonatedPrincipal attribute.  About halfway 
down, you'll see the sessionId that I actually stored the 
impersonatedPrincipal in.

ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
ImpersonateFilter: FFB83D207968FBF944D36E86F50A8871
ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
ImpersonateFilter: 20121D0DA12AC42E95F0567820D925EA
ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
ImpersonateFilter: FFB83D207968FBF944D36E86F50A8871
ImpersonateFilter: FFB83D207968FBF944D36E86F50A8871
ImpersonateFilter: FFB83D207968FBF944D36E86F50A8871
ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
ImpersonateFilter: 6A71E7CB18268BAD8A8A2427D264A794
Set session attribute: E6412E5B6419E06D5233F53D40D88E9E
ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
ImpersonateFilter: 640691F73EB2139A1BA88E47D2FB189F
ImpersonateFilter: 640691F73EB2139A1BA88E47D2FB189F
ImpersonateFilter: 640691F73EB2139A1BA88E47D2FB189F
ImpersonateFilter: 20121D0DA12AC42E95F0567820D925EA
ImpersonateFilter: 640691F73EB2139A1BA88E47D2FB189F
ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A
ImpersonateFilter: F4D2C34AEBF4980D796D126EA99EE22A

Re: Admin password for Tomcat

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Jerry,

On 12/28/23 18:33, Jerry Malcolm wrote:
> Chris,
> 
> On 12/28/2023 3:38 PM, Christopher Schultz wrote:
>> Jerry.
>>
>> On 12/27/23 02:13, Jerry Malcolm wrote:
>>> I implemented the filter as you suggested.  But I guess I'm going to 
>>> need some education on sessions.  Down in a user profile web page I 
>>> have a button to "Impersonate".
>>
>> I'm with you so far.
>>
>>> I create the GenericPrincipal object and store it in the session. 
>>> I've checked several times, and every time I come back to that code, 
>>> the attribute is set in the session object.
>>
>> Good. When you do that, do you remove the "real" user's 
>> GenericPrincipal object from the session? Or are they both in there?
 >
> Sorry... lost you on that one.  I am just setting a custom  > "GenericPrincipal" attribute named "impersonatedPrincipal" in the
> session when a user clicks the "Impersonate" button on the web page.

This answers my question. I was wondering if you do this:

session.setAttribute("user", impersonatedUser); // Replace

or this:

session.setAttribut("impersonatedUser", impersonatedUser);

And it seems you are doing the second one.

> In my understanding, at this point I'm just 'telling' the session
> that on subsequent requests in the custom filter, here's a principal
> object that I want to insert.
As long as your code agrees with you :)

> I also noted in your early example that you stored a 
> 'User' class as the attribute in the session, not a GenericPrincipal.  I 
> couldn't find a "User" class.  So I just used GenericPrincipal, since 
> that was what I will insert in the request object in the filter.

We use User in our session, and essentially wrap it in a 
GenericPrincipal when necessary. We are playing a lot of games, here, in 
our code, so I apologize if we go down this road and it's a lot longer 
than you had expected...

>> Remember that if Tomcat is going to enforce your authentication and 
>> authorization constraints, your Filter will run after that, and Tomcat 
>> and your application will disagree over which user is currently 
>> logged-in.
 >
> I'm not removing the real principal from anything.  Not sure how to do 
> that?  in HttpSession?  in HttpRequest?  I assumed returning my new 
> GenericPrincipal in the RequestFacade would override any other code 
> asking for the principal.

It will... unless that code runs before your Filter has a chance to pull 
the wool over the application's eyes. For example... Tomcat's 
authentication and authorization code will run in a Valve, which runs 
before all Filters.

> How do I go about removing the real principal?

Let's save that for later ;)

>>> But when I put breakpoint in my new Filter object and look in the
>>> session, no attribute.  It's a different session object from what I
>>> can tell.
>> That's weird.
>>
>> When you say "every time I come back to that code, the attribute is 
>> set in the session" ... what code are you taking about?
 >
> The filter's 'version' of the session doesn't have the 
> "impersonatedPrincipal" attribute set (it doesn't have any attributes 
> set).  But after clicking Impersonate, hitting the breakpoint, and 
> watching the session attribute get set, I hit F5 to refresh the page. 
> The filter breakpoint again doesn't have the attribute.  But if I click 
> "Impersonate" again and hit that breakpoint the "impersonatedPrincipal" 
> session attribute exists in the session.

Is the session identifier changing?

>>> I really thought I understood session objects.  I thought there was 
>>> only one session object throughout the processing of a servlet.
>>
>> Yes, if s/servlet/request/.
>>
>>> But I'm obviously missing something in the flows.  Why is there a
>>> different session object in the filter than in the main body of the
>>> servlet?  I did the getSession(false) as you suggested.  The session
>>> object is not null.  It just doesn't have the attribute set. Yet if
>>> I hit the Impersonate button again and hit the breakpoint, the
>>> GenericPrincipal attribute is sitting in the session just as I placed
>>> it earlier.
>> If the difference between when Tomcat evaluates e.g. user-roles versus 
>> when your application does won't explain what's happening, we might 
>> need to see some code.
> 
> Code:
> 
> Other than a loop that builds a Roles vector, these are the two lines 
> that create the session attribute when the "Impersonate" button is clicked.
> 
> GenericPrincipal newPrincipal = new GenericPrincipal( getUserName(),
> getPassword(),
> roles );
>        getCtrl().getRequest().getSession(false).setAttribute( 
> "impersonatedPrincipal", newPrincipal );

Hmm. What are Ctrl and Request that you are "getting"? Usually, both the 
servlet and the Filter see objects passed to them directly in the 
doFilter() and service()/doGet/doPost/whatever methods in the servlet.

> And this is the filter:
> 
>        PrintWriter out = response.getWriter();
> 
>        HttpSession session = 
> ((HttpServletRequest)request).getSession(false);
>        if(session != null)
>        {
>           final GenericPrincipal impersonatedPrincipal = 
> (GenericPrincipal) session.getAttribute("impersonatedPrincipal");
>           if (impersonatedPrincipal != null)
>           {
>              System.out.println( "Impersonating");
>              request = new 
> HttpServletRequestWrapper((HttpServletRequest)request)
>              {
>                 public Principal getUserPrincipal()
>                 {
>                    return impersonatedPrincipal;
>                 }
>              };
>           }
>        }
>        chain.doFilter(request, response);
> 
> I feel like I'm right on top of the solution.  But I just can't seem to 
> get over the finish line. Thanks for you help.

Filter looks good. The other code looks sus.

-chris

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Admin password for Tomcat

Posted by Jerry Malcolm <te...@malcolms.com>.
Chris,

On 12/28/2023 3:38 PM, Christopher Schultz wrote:
> Jerry.
>
> On 12/27/23 02:13, Jerry Malcolm wrote:
>> I implemented the filter as you suggested.  But I guess I'm going to 
>> need some education on sessions.  Down in a user profile web page I 
>> have a button to "Impersonate".
>
> I'm with you so far.
>
>> I create the GenericPrincipal object and store it in the session.  
>> I've checked several times, and every time I come back to that code, 
>> the attribute is set in the session object.
>
> Good. When you do that, do you remove the "real" user's 
> GenericPrincipal object from the session? Or are they both in there?
Sorry... lost you on that one.  I am just setting a custom 
"GenericPrincipal" attribute named "impersonatedPrincipal" in the 
session when a user clicks the "Impersonate" button on the web page.  In 
my understanding, at this point I'm just 'telling' the session that on 
subsequent requests in the custom filter, here's a principal object that 
I want to insert.  I also noted in your early example that you stored a 
'User' class as the attribute in the session, not a GenericPrincipal.  I 
couldn't find a "User" class.  So I just used GenericPrincipal, since 
that was what I will insert in the request object in the filter.
>
> Remember that if Tomcat is going to enforce your authentication and 
> authorization constraints, your Filter will run after that, and Tomcat 
> and your application will disagree over which user is currently 
> logged-in.
I'm not removing the real principal from anything.  Not sure how to do 
that?  in HttpSession?  in HttpRequest?  I assumed returning my new 
GenericPrincipal in the RequestFacade would override any other code 
asking for the principal.  How do I go about removing the real principal?
>
>> But when I put breakpoint in my new Filter object and look in the
>> session, no attribute.  It's a different session object from what I
>> can tell.
> That's weird.
>
> When you say "every time I come back to that code, the attribute is 
> set in the session" ... what code are you taking about?
The filter's 'version' of the session doesn't have the 
"impersonatedPrincipal" attribute set (it doesn't have any attributes 
set).  But after clicking Impersonate, hitting the breakpoint, and 
watching the session attribute get set, I hit F5 to refresh the page.  
The filter breakpoint again doesn't have the attribute.  But if I click 
"Impersonate" again and hit that breakpoint the "impersonatedPrincipal" 
session attribute exists in the session.
>
>> I really thought I understood session objects.  I thought there was 
>> only one session object throughout the processing of a servlet.
>
> Yes, if s/servlet/request/.
>
>> But I'm obviously missing something in the flows.  Why is there a
>> different session object in the filter than in the main body of the
>> servlet?  I did the getSession(false) as you suggested.  The session
>> object is not null.  It just doesn't have the attribute set. Yet if
>> I hit the Impersonate button again and hit the breakpoint, the
>> GenericPrincipal attribute is sitting in the session just as I placed
>> it earlier.
> If the difference between when Tomcat evaluates e.g. user-roles versus 
> when your application does won't explain what's happening, we might 
> need to see some code.

Code:

Other than a loop that builds a Roles vector, these are the two lines 
that create the session attribute when the "Impersonate" button is clicked.

GenericPrincipal newPrincipal = new GenericPrincipal( getUserName(),
getPassword(),
roles );
       getCtrl().getRequest().getSession(false).setAttribute( 
"impersonatedPrincipal", newPrincipal );

And this is the filter:

       PrintWriter out = response.getWriter();

       HttpSession session = 
((HttpServletRequest)request).getSession(false);
       if(session != null)
       {
          final GenericPrincipal impersonatedPrincipal = 
(GenericPrincipal) session.getAttribute("impersonatedPrincipal");
          if (impersonatedPrincipal != null)
          {
             System.out.println( "Impersonating");
             request = new 
HttpServletRequestWrapper((HttpServletRequest)request)
             {
                public Principal getUserPrincipal()
                {
                   return impersonatedPrincipal;
                }
             };
          }
       }
       chain.doFilter(request, response);

I feel like I'm right on top of the solution.  But I just can't seem to 
get over the finish line. Thanks for you help.

>
> -chris
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>

Re: Admin password for Tomcat

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Jerry.

On 12/27/23 02:13, Jerry Malcolm wrote:
> I implemented the filter as you suggested.  But I guess I'm going to 
> need some education on sessions.  Down in a user profile web page I have 
> a button to "Impersonate".

I'm with you so far.

> I create the GenericPrincipal object and 
> store it in the session.  I've checked several times, and every time I 
> come back to that code, the attribute is set in the session object.

Good. When you do that, do you remove the "real" user's GenericPrincipal 
object from the session? Or are they both in there?

Remember that if Tomcat is going to enforce your authentication and 
authorization constraints, your Filter will run after that, and Tomcat 
and your application will disagree over which user is currently logged-in.

> But when I put breakpoint in my new Filter object and look in the
> session, no attribute.  It's a different session object from what I
> can tell.
That's weird.

When you say "every time I come back to that code, the attribute is set 
in the session" ... what code are you taking about?

> I 
> really thought I understood session objects.  I thought there was only 
> one session object throughout the processing of a servlet.

Yes, if s/servlet/request/.

> But I'm obviously missing something in the flows.  Why is there a
> different session object in the filter than in the main body of the
> servlet?  I did the getSession(false) as you suggested.  The session
> object is not null.  It just doesn't have the attribute set.  Yet if
> I hit the Impersonate button again and hit the breakpoint, the
> GenericPrincipal attribute is sitting in the session just as I placed
> it earlier.
If the difference between when Tomcat evaluates e.g. user-roles versus 
when your application does won't explain what's happening, we might need 
to see some code.

-chris

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Admin password for Tomcat

Posted by Jerry Malcolm <te...@malcolms.com>.
Chris,

On 12/26/2023 11:35 AM, Christopher Schultz wrote:
> Jerry,
>
> On 12/24/23 19:18, Jerry Malcolm wrote:
>> Chris,
>>
>> On 11/8/2023 2:43 PM, Christopher Schultz wrote:
>>> Jerry,
>>>
>>> On 11/6/23 23:22, Jerry Malcolm wrote:
>>>>
>>>> On 11/5/2023 11:54 AM, Jerry Malcolm wrote:
>>>>>
>>>>> On 11/5/2023 9:26 AM, Christopher Schultz wrote:
>>>>>> Jerry,
>>>>>>
>>>>>> On 11/4/23 20:17, Jerry Malcolm wrote:
>>>>>>> My support team needs to be able to log in to our site as 
>>>>>>> various users (on behalf of...) to be able to see exactly what 
>>>>>>> they are seeing since roles, access groups, history is different 
>>>>>>> for different users. I would like to implement an admin password 
>>>>>>> where I can log in as any userId with this password.  I totally 
>>>>>>> realize the security risks involved in this.  But I am handling 
>>>>>>> the security risks with additional authorizations.  I simply 
>>>>>>> need to make every user have two passwords... their real 
>>>>>>> personal password, and the admin password.  The only alternative 
>>>>>>> I have right now is to save off the user's password hash in the 
>>>>>>> USERS table, replace it with my password hash, then restore the 
>>>>>>> user's original password when I'm done.  I'm not thrilled with 
>>>>>>> that solution first because it's a pain and error prone, and 
>>>>>>> also because the user can no longer log in while their password 
>>>>>>> is replaced with my password.
>>>>>>>
>>>>>>>   I figure this function is buried in the authenticator code 
>>>>>>> somewhere. But I'd first like to see if anybody has done 
>>>>>>> anything like this already. If not, could somebody point me in 
>>>>>>> the right direction to the tomcat source file that I'm going to 
>>>>>>> need to modify and also what's involved in making authentication 
>>>>>>> use my updated class instead of the default.
>>>>>>>
>>>>>>> Suggestions?
>>>>>>
>>>>>> This sounds like "impersonation" to me, which, I think, can be 
>>>>>> done differently. If you are indeed describing an X-Y problem 
>>>>>> above, then might I suggest the following?
>>>>>>
>>>>>> Instead of figuring out how to "add" a second password to a user, 
>>>>>> what about allowing you to login as e.g. "jerry" and then assume 
>>>>>> the identity of the user "tom"? You should be able to do this by 
>>>>>> changing the UserPrincipal in the session to have a different 
>>>>>> username.
>>>>>>
>>>>>> Which application are you trying to do this with? Your own 
>>>>>> application, or one which ships with Tomcat (e.g. Manager)?
>>>>>>
>>>>>> -chris
>>>>>
>>>>> Hi Chris, it's my own webapp.  Changing user principal is exactly 
>>>>> what I'm trying to do.  I wasn't aware that the user principal 
>>>>> could be easily swapped.  Where can I learn more about how to do 
>>>>> that?
>>>>>
>>>> Chris, I'm not having any luck googling info on how to replace the 
>>>> user principal object in the session object. This is exactly what I 
>>>> need to do.  But looks like I'm going to need a little bit of 
>>>> guidance to figure out how to implement it.
>>>
>>> I forgot that "we" are using our own custom principal and actually 
>>> not using Tomcat's authentication and authorization. So we do things 
>>> differently.
>>>
>>> If you are using FORM authentication, then I think this is a little 
>>> easier.
>>>
>>> You may have to do a nasty bit of casting to internal Tomcat classes 
>>> and/or use reflection, but you can simply call:
>>>
>>> org.apache.catalina.Session.setPrincipal(java.security.Principal)
>>>
>>> The StandardSession class you probably are already getting from 
>>> Tomcat implements that interface, so you should be able to call that.
>>>
>>> I think while Tomcat will accept any java.security.Principal, in 
>>> practice, you'll want to use 
>>> org.apache.catalina.realm.GenericPrincipal.
>>>
>>> -chris
>>
>> I finally had a minute to try to implement your suggestion from a few 
>> weeks ago.  I got everything coded.  But I'm getting a 
>> ClassCastException  when trying to retrieve StandardSession. I'm 
>> getting a StandardSessionFacade object instead of StandardSession.  I 
>> looked at the javaDoc hoping to find a way to get the StandardSession 
>> from the facade object.  But no luck.   Am I not going about this 
>> correctly in my code?  How can get access to the StandardSession 
>> object instead of the StandardSessionFacade object?  Thx
>>
>>        GenericPrincipal newPrincipal = new GenericPrincipal( 
>> getUserName(),  getPassword(),  roles );
>> ((StandardSession)getCtrl().getRequest().getSession()).setPrincipal( 
>> newPrincipal );
>
> Hmm. It seems that StandardSessionFacade is used to prevent the kind 
> of thing you are trying to do, probably as a protection against 
> potentially malicious applications.
>
> If you are willing to get messier, you can use reflection to get the 
> value of the StandardSessionFacade.session member, which will be a 
> StandardSession object.
>
> Another option is to do what my application does, which is to store 
> the user in a session attribute and then wrap each request in a Filter 
> making it available:
>
> doFilter(...) {
>   HttpSession s = request.getSession(false);
>
>   if(null != s) {
>     final User u = s.getAttribute("user");
>     if(null != u) {
>       // Wrap request
>       request = new HttpServletRequestWrapper(request) {
>         public Principal getUserPrincipal() {
>           return u;
>         }
>       };
>     }
>   }
>
>   chain.doFilter(request, response);
> }
>
> The above is psuedocode typed from memory. I'm fairly sure we create a 
> new Principal object because our User object doesn't actually 
> implement Principal.
>
> -chris
I implemented the filter as you suggested.  But I guess I'm going to 
need some education on sessions.  Down in a user profile web page I have 
a button to "Impersonate".  I create the GenericPrincipal object and 
store it in the session.  I've checked several times, and every time I 
come back to that code, the attribute is set in the session object.  But 
when I put breakpoint in my new Filter object and look in the session, 
no attribute.  It's a different session object from what I can tell.  I 
really thought I understood session objects.  I thought there was only 
one session object throughout the processing of a servlet.  But I'm 
obviously missing something in the flows.  Why is there a different 
session object in the filter than in the main body of the servlet?  I 
did the getSession(false) as you suggested.  The session object is not 
null.  It just doesn't have the attribute set.  Yet if I hit the 
Impersonate button again and hit the breakpoint, the GenericPrincipal 
attribute is sitting in the session just as I placed it earlier.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Admin password for Tomcat

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Jerry,

On 12/24/23 19:18, Jerry Malcolm wrote:
> Chris,
> 
> On 11/8/2023 2:43 PM, Christopher Schultz wrote:
>> Jerry,
>>
>> On 11/6/23 23:22, Jerry Malcolm wrote:
>>>
>>> On 11/5/2023 11:54 AM, Jerry Malcolm wrote:
>>>>
>>>> On 11/5/2023 9:26 AM, Christopher Schultz wrote:
>>>>> Jerry,
>>>>>
>>>>> On 11/4/23 20:17, Jerry Malcolm wrote:
>>>>>> My support team needs to be able to log in to our site as various 
>>>>>> users (on behalf of...) to be able to see exactly what they are 
>>>>>> seeing since roles, access groups, history is different for 
>>>>>> different users. I would like to implement an admin password where 
>>>>>> I can log in as any userId with this password.  I totally realize 
>>>>>> the security risks involved in this.  But I am handling the 
>>>>>> security risks with additional authorizations.  I simply need to 
>>>>>> make every user have two passwords... their real personal 
>>>>>> password, and the admin password.  The only alternative I have 
>>>>>> right now is to save off the user's password hash in the USERS 
>>>>>> table, replace it with my password hash, then restore the user's 
>>>>>> original password when I'm done.  I'm not thrilled with that 
>>>>>> solution first because it's a pain and error prone, and also 
>>>>>> because the user can no longer log in while their password is 
>>>>>> replaced with my password.
>>>>>>
>>>>>>   I figure this function is buried in the authenticator code 
>>>>>> somewhere. But I'd first like to see if anybody has done anything 
>>>>>> like this already.  If not, could somebody point me in the right 
>>>>>> direction to the tomcat source file that I'm going to need to 
>>>>>> modify and also what's involved in making authentication use my 
>>>>>> updated class instead of the default.
>>>>>>
>>>>>> Suggestions?
>>>>>
>>>>> This sounds like "impersonation" to me, which, I think, can be done 
>>>>> differently. If you are indeed describing an X-Y problem above, 
>>>>> then might I suggest the following?
>>>>>
>>>>> Instead of figuring out how to "add" a second password to a user, 
>>>>> what about allowing you to login as e.g. "jerry" and then assume 
>>>>> the identity of the user "tom"? You should be able to do this by 
>>>>> changing the UserPrincipal in the session to have a different 
>>>>> username.
>>>>>
>>>>> Which application are you trying to do this with? Your own 
>>>>> application, or one which ships with Tomcat (e.g. Manager)?
>>>>>
>>>>> -chris
>>>>
>>>> Hi Chris, it's my own webapp.  Changing user principal is exactly 
>>>> what I'm trying to do.  I wasn't aware that the user principal could 
>>>> be easily swapped.  Where can I learn more about how to do that?
>>>>
>>> Chris, I'm not having any luck googling info on how to replace the 
>>> user principal object in the session object.  This is exactly what I 
>>> need to do.  But looks like I'm going to need a little bit of 
>>> guidance to figure out how to implement it.
>>
>> I forgot that "we" are using our own custom principal and actually not 
>> using Tomcat's authentication and authorization. So we do things 
>> differently.
>>
>> If you are using FORM authentication, then I think this is a little 
>> easier.
>>
>> You may have to do a nasty bit of casting to internal Tomcat classes 
>> and/or use reflection, but you can simply call:
>>
>> org.apache.catalina.Session.setPrincipal(java.security.Principal)
>>
>> The StandardSession class you probably are already getting from Tomcat 
>> implements that interface, so you should be able to call that.
>>
>> I think while Tomcat will accept any java.security.Principal, in 
>> practice, you'll want to use org.apache.catalina.realm.GenericPrincipal.
>>
>> -chris
> 
> I finally had a minute to try to implement your suggestion from a few 
> weeks ago.  I got everything coded.  But I'm getting a 
> ClassCastException  when trying to retrieve StandardSession.  I'm 
> getting a StandardSessionFacade object instead of StandardSession.  I 
> looked at the javaDoc hoping to find a way to get the StandardSession 
> from the facade object.  But no luck.   Am I not going about this 
> correctly in my code?  How can get access to the StandardSession object 
> instead of the StandardSessionFacade object?  Thx
> 
>        GenericPrincipal newPrincipal = new GenericPrincipal( 
> getUserName(),  getPassword(),  roles );
> ((StandardSession)getCtrl().getRequest().getSession()).setPrincipal( 
> newPrincipal );

Hmm. It seems that StandardSessionFacade is used to prevent the kind of 
thing you are trying to do, probably as a protection against potentially 
malicious applications.

If you are willing to get messier, you can use reflection to get the 
value of the StandardSessionFacade.session member, which will be a 
StandardSession object.

Another option is to do what my application does, which is to store the 
user in a session attribute and then wrap each request in a Filter 
making it available:

doFilter(...) {
   HttpSession s = request.getSession(false);

   if(null != s) {
     final User u = s.getAttribute("user");
     if(null != u) {
       // Wrap request
       request = new HttpServletRequestWrapper(request) {
         public Principal getUserPrincipal() {
           return u;
         }
       };
     }
   }

   chain.doFilter(request, response);
}

The above is psuedocode typed from memory. I'm fairly sure we create a 
new Principal object because our User object doesn't actually implement 
Principal.

-chris

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Admin password for Tomcat

Posted by Jerry Malcolm <te...@malcolms.com>.
Chris,

On 11/8/2023 2:43 PM, Christopher Schultz wrote:
> Jerry,
>
> On 11/6/23 23:22, Jerry Malcolm wrote:
>>
>> On 11/5/2023 11:54 AM, Jerry Malcolm wrote:
>>>
>>> On 11/5/2023 9:26 AM, Christopher Schultz wrote:
>>>> Jerry,
>>>>
>>>> On 11/4/23 20:17, Jerry Malcolm wrote:
>>>>> My support team needs to be able to log in to our site as various 
>>>>> users (on behalf of...) to be able to see exactly what they are 
>>>>> seeing since roles, access groups, history is different for 
>>>>> different users. I would like to implement an admin password where 
>>>>> I can log in as any userId with this password.  I totally realize 
>>>>> the security risks involved in this.  But I am handling the 
>>>>> security risks with additional authorizations.  I simply need to 
>>>>> make every user have two passwords... their real personal 
>>>>> password, and the admin password.  The only alternative I have 
>>>>> right now is to save off the user's password hash in the USERS 
>>>>> table, replace it with my password hash, then restore the user's 
>>>>> original password when I'm done.  I'm not thrilled with that 
>>>>> solution first because it's a pain and error prone, and also 
>>>>> because the user can no longer log in while their password is 
>>>>> replaced with my password.
>>>>>
>>>>>   I figure this function is buried in the authenticator code 
>>>>> somewhere. But I'd first like to see if anybody has done anything 
>>>>> like this already.  If not, could somebody point me in the right 
>>>>> direction to the tomcat source file that I'm going to need to 
>>>>> modify and also what's involved in making authentication use my 
>>>>> updated class instead of the default.
>>>>>
>>>>> Suggestions?
>>>>
>>>> This sounds like "impersonation" to me, which, I think, can be done 
>>>> differently. If you are indeed describing an X-Y problem above, 
>>>> then might I suggest the following?
>>>>
>>>> Instead of figuring out how to "add" a second password to a user, 
>>>> what about allowing you to login as e.g. "jerry" and then assume 
>>>> the identity of the user "tom"? You should be able to do this by 
>>>> changing the UserPrincipal in the session to have a different 
>>>> username.
>>>>
>>>> Which application are you trying to do this with? Your own 
>>>> application, or one which ships with Tomcat (e.g. Manager)?
>>>>
>>>> -chris
>>>
>>> Hi Chris, it's my own webapp.  Changing user principal is exactly 
>>> what I'm trying to do.  I wasn't aware that the user principal could 
>>> be easily swapped.  Where can I learn more about how to do that?
>>>
>> Chris, I'm not having any luck googling info on how to replace the 
>> user principal object in the session object.  This is exactly what I 
>> need to do.  But looks like I'm going to need a little bit of 
>> guidance to figure out how to implement it.
>
> I forgot that "we" are using our own custom principal and actually not 
> using Tomcat's authentication and authorization. So we do things 
> differently.
>
> If you are using FORM authentication, then I think this is a little 
> easier.
>
> You may have to do a nasty bit of casting to internal Tomcat classes 
> and/or use reflection, but you can simply call:
>
> org.apache.catalina.Session.setPrincipal(java.security.Principal)
>
> The StandardSession class you probably are already getting from Tomcat 
> implements that interface, so you should be able to call that.
>
> I think while Tomcat will accept any java.security.Principal, in 
> practice, you'll want to use org.apache.catalina.realm.GenericPrincipal.
>
> -chris

I finally had a minute to try to implement your suggestion from a few 
weeks ago.  I got everything coded.  But I'm getting a 
ClassCastException  when trying to retrieve StandardSession.  I'm 
getting a StandardSessionFacade object instead of StandardSession.  I 
looked at the javaDoc hoping to find a way to get the StandardSession 
from the facade object.  But no luck.   Am I not going about this 
correctly in my code?  How can get access to the StandardSession object 
instead of the StandardSessionFacade object?  Thx

       GenericPrincipal newPrincipal = new GenericPrincipal( 
getUserName(),  getPassword(),  roles );
((StandardSession)getCtrl().getRequest().getSession()).setPrincipal( 
newPrincipal );


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Admin password for Tomcat

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Jerry,

On 11/6/23 23:22, Jerry Malcolm wrote:
> 
> On 11/5/2023 11:54 AM, Jerry Malcolm wrote:
>>
>> On 11/5/2023 9:26 AM, Christopher Schultz wrote:
>>> Jerry,
>>>
>>> On 11/4/23 20:17, Jerry Malcolm wrote:
>>>> My support team needs to be able to log in to our site as various 
>>>> users (on behalf of...) to be able to see exactly what they are 
>>>> seeing since roles, access groups, history is different for 
>>>> different users.  I would like to implement an admin password where 
>>>> I can log in as any userId with this password.  I totally realize 
>>>> the security risks involved in this.  But I am handling the security 
>>>> risks with additional authorizations.  I simply need to make every 
>>>> user have two passwords... their real personal password, and the 
>>>> admin password.  The only alternative I have right now is to save 
>>>> off the user's password hash in the USERS table, replace it with my 
>>>> password hash, then restore the user's original password when I'm 
>>>> done.  I'm not thrilled with that solution first because it's a pain 
>>>> and error prone, and also because the user can no longer log in 
>>>> while their password is replaced with my password.
>>>>
>>>>   I figure this function is buried in the authenticator code 
>>>> somewhere. But I'd first like to see if anybody has done anything 
>>>> like this already.  If not, could somebody point me in the right 
>>>> direction to the tomcat source file that I'm going to need to modify 
>>>> and also what's involved in making authentication use my updated 
>>>> class instead of the default.
>>>>
>>>> Suggestions?
>>>
>>> This sounds like "impersonation" to me, which, I think, can be done 
>>> differently. If you are indeed describing an X-Y problem above, then 
>>> might I suggest the following?
>>>
>>> Instead of figuring out how to "add" a second password to a user, 
>>> what about allowing you to login as e.g. "jerry" and then assume the 
>>> identity of the user "tom"? You should be able to do this by changing 
>>> the UserPrincipal in the session to have a different username.
>>>
>>> Which application are you trying to do this with? Your own 
>>> application, or one which ships with Tomcat (e.g. Manager)?
>>>
>>> -chris
>>
>> Hi Chris, it's my own webapp.  Changing user principal is exactly what 
>> I'm trying to do.  I wasn't aware that the user principal could be 
>> easily swapped.  Where can I learn more about how to do that?
>>
> Chris, I'm not having any luck googling info on how to replace the user 
> principal object in the session object.  This is exactly what I need to 
> do.  But looks like I'm going to need a little bit of guidance to figure 
> out how to implement it.

I forgot that "we" are using our own custom principal and actually not 
using Tomcat's authentication and authorization. So we do things 
differently.

If you are using FORM authentication, then I think this is a little easier.

You may have to do a nasty bit of casting to internal Tomcat classes 
and/or use reflection, but you can simply call:

org.apache.catalina.Session.setPrincipal(java.security.Principal)

The StandardSession class you probably are already getting from Tomcat 
implements that interface, so you should be able to call that.

I think while Tomcat will accept any java.security.Principal, in 
practice, you'll want to use org.apache.catalina.realm.GenericPrincipal.

-chris

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Admin password for Tomcat

Posted by Jerry Malcolm <te...@malcolms.com>.
On 11/5/2023 11:54 AM, Jerry Malcolm wrote:
>
> On 11/5/2023 9:26 AM, Christopher Schultz wrote:
>> Jerry,
>>
>> On 11/4/23 20:17, Jerry Malcolm wrote:
>>> My support team needs to be able to log in to our site as various 
>>> users (on behalf of...) to be able to see exactly what they are 
>>> seeing since roles, access groups, history is different for 
>>> different users.  I would like to implement an admin password where 
>>> I can log in as any userId with this password.  I totally realize 
>>> the security risks involved in this.  But I am handling the security 
>>> risks with additional authorizations.  I simply need to make every 
>>> user have two passwords... their real personal password, and the 
>>> admin password.  The only alternative I have right now is to save 
>>> off the user's password hash in the USERS table, replace it with my 
>>> password hash, then restore the user's original password when I'm 
>>> done.  I'm not thrilled with that solution first because it's a pain 
>>> and error prone, and also because the user can no longer log in 
>>> while their password is replaced with my password.
>>>
>>>   I figure this function is buried in the authenticator code 
>>> somewhere. But I'd first like to see if anybody has done anything 
>>> like this already.  If not, could somebody point me in the right 
>>> direction to the tomcat source file that I'm going to need to modify 
>>> and also what's involved in making authentication use my updated 
>>> class instead of the default.
>>>
>>> Suggestions?
>>
>> This sounds like "impersonation" to me, which, I think, can be done 
>> differently. If you are indeed describing an X-Y problem above, then 
>> might I suggest the following?
>>
>> Instead of figuring out how to "add" a second password to a user, 
>> what about allowing you to login as e.g. "jerry" and then assume the 
>> identity of the user "tom"? You should be able to do this by changing 
>> the UserPrincipal in the session to have a different username.
>>
>> Which application are you trying to do this with? Your own 
>> application, or one which ships with Tomcat (e.g. Manager)?
>>
>> -chris
>
> Hi Chris, it's my own webapp.  Changing user principal is exactly what 
> I'm trying to do.  I wasn't aware that the user principal could be 
> easily swapped.  Where can I learn more about how to do that?
>
Chris, I'm not having any luck googling info on how to replace the user 
principal object in the session object.  This is exactly what I need to 
do.  But looks like I'm going to need a little bit of guidance to figure 
out how to implement it.

Thanks.

Jerry


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Admin password for Tomcat

Posted by Jerry Malcolm <te...@malcolms.com>.
On 11/5/2023 9:26 AM, Christopher Schultz wrote:
> Jerry,
>
> On 11/4/23 20:17, Jerry Malcolm wrote:
>> My support team needs to be able to log in to our site as various 
>> users (on behalf of...) to be able to see exactly what they are 
>> seeing since roles, access groups, history is different for different 
>> users.  I would like to implement an admin password where I can log 
>> in as any userId with this password.  I totally realize the security 
>> risks involved in this.  But I am handling the security risks with 
>> additional authorizations.  I simply need to make every user have two 
>> passwords... their real personal password, and the admin password.  
>> The only alternative I have right now is to save off the user's 
>> password hash in the USERS table, replace it with my password hash, 
>> then restore the user's original password when I'm done.  I'm not 
>> thrilled with that solution first because it's a pain and error 
>> prone, and also because the user can no longer log in while their 
>> password is replaced with my password.
>>
>>   I figure this function is buried in the authenticator code 
>> somewhere. But I'd first like to see if anybody has done anything 
>> like this already.  If not, could somebody point me in the right 
>> direction to the tomcat source file that I'm going to need to modify 
>> and also what's involved in making authentication use my updated 
>> class instead of the default.
>>
>> Suggestions?
>
> This sounds like "impersonation" to me, which, I think, can be done 
> differently. If you are indeed describing an X-Y problem above, then 
> might I suggest the following?
>
> Instead of figuring out how to "add" a second password to a user, what 
> about allowing you to login as e.g. "jerry" and then assume the 
> identity of the user "tom"? You should be able to do this by changing 
> the UserPrincipal in the session to have a different username.
>
> Which application are you trying to do this with? Your own 
> application, or one which ships with Tomcat (e.g. Manager)?
>
> -chris

Hi Chris, it's my own webapp.  Changing user principal is exactly what 
I'm trying to do.  I wasn't aware that the user principal could be 
easily swapped.  Where can I learn more about how to do that?


> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Admin password for Tomcat

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Jerry,

On 11/4/23 20:17, Jerry Malcolm wrote:
> My support team needs to be able to log in to our site as various users 
> (on behalf of...) to be able to see exactly what they are seeing since 
> roles, access groups, history is different for different users.  I would 
> like to implement an admin password where I can log in as any userId 
> with this password.  I totally realize the security risks involved in 
> this.  But I am handling the security risks with additional 
> authorizations.  I simply need to make every user have two passwords... 
> their real personal password, and the admin password.  The only 
> alternative I have right now is to save off the user's password hash in 
> the USERS table, replace it with my password hash, then restore the 
> user's original password when I'm done.  I'm not thrilled with that 
> solution first because it's a pain and error prone, and also because the 
> user can no longer log in while their password is replaced with my 
> password.
> 
>   I figure this function is buried in the authenticator code somewhere. 
> But I'd first like to see if anybody has done anything like this 
> already.  If not, could somebody point me in the right direction to the 
> tomcat source file that I'm going to need to modify and also what's 
> involved in making authentication use my updated class instead of the 
> default.
> 
> Suggestions?

This sounds like "impersonation" to me, which, I think, can be done 
differently. If you are indeed describing an X-Y problem above, then 
might I suggest the following?

Instead of figuring out how to "add" a second password to a user, what 
about allowing you to login as e.g. "jerry" and then assume the identity 
of the user "tom"? You should be able to do this by changing the 
UserPrincipal in the session to have a different username.

Which application are you trying to do this with? Your own application, 
or one which ships with Tomcat (e.g. Manager)?

-chris

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Admin password for Tomcat

Posted by Peter Kreuser <lo...@kreuser.name>.
Jerry,

> Am 05.11.2023 um 02:34 schrieb Brian Wolfe <wo...@gmail.com>:
> 
> You need to build a custom realm for that if you're using tomcat to manage
> your user sessions and not creating your own sessions for your application.
> You can extend the existing one that you're using. I assume you're using
> the JDBC Realm since you said you have an USERS table. So you could add
> another field to your table and extend the JDBC class to do an additional
> check on your admin pwd field if you don't want them to have a second
> account.
> 
> https://tomcat.apache.org/tomcat-9.0-doc/realm-howto.html#Standard_Realm_Implementations
> 
> You will want to look at the source of the realm implementation to see how
> you need to extend it. So you shouldn't have to do too much to get the
> functionality you're looking for.
> 
>> On Sat, Nov 4, 2023 at 8:18 PM Jerry Malcolm <te...@malcolms.com> wrote:
>> 
>> My support team needs to be able to log in to our site as various users
>> (on behalf of...) to be able to see exactly what they are seeing since
>> roles, access groups, history is different for different users.  I would
>> like to implement an admin password where I can log in as any userId
>> with this password.  I totally realize the security risks involved in
>> this.  But I am handling the security risks with additional
>> authorizations.

Back in the days when we had this requirement, we implemented an "admin tool" where we had the admin user login as themselves and then pick the user they wanted to see. At this time the password check was simply skipped. No fiddling with the password table, no security flaws as the admin tool was not available to the public.

>>  I simply need to make every user have two passwords...
>> their real personal password, and the admin password.  The only
>> alternative I have right now is to save off the user's password hash in
>> the USERS table, replace it with my password hash, then restore the
>> user's original password when I'm done.  I'm not thrilled with that
>> solution first because it's a pain and error prone, and also because the
>> user can no longer log in while their password is replaced with my
>> password.
>> 
>>  I figure this function is buried in the authenticator code somewhere.
>> But I'd first like to see if anybody has done anything like this
>> already.  If not, could somebody point me in the right direction to the
>> tomcat source file that I'm going to need to modify and also what's
>> involved in making authentication use my updated class instead of the
>> default.
>> 
>> Suggestions?
>> 

Would that be a solution?

Peter

>> Thx
>> 
>> Jerry
>> 
>> 
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>> For additional commands, e-mail: users-help@tomcat.apache.org
>> 
>> 
> 
> --
> Thanks,
> Brian Wolfe
> https://www.linkedin.com/in/brian-wolfe-3136425a/

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Admin password for Tomcat

Posted by Brian Wolfe <wo...@gmail.com>.
You need to build a custom realm for that if you're using tomcat to manage
your user sessions and not creating your own sessions for your application.
You can extend the existing one that you're using. I assume you're using
the JDBC Realm since you said you have an USERS table. So you could add
another field to your table and extend the JDBC class to do an additional
check on your admin pwd field if you don't want them to have a second
account.

https://tomcat.apache.org/tomcat-9.0-doc/realm-howto.html#Standard_Realm_Implementations

You will want to look at the source of the realm implementation to see how
you need to extend it. So you shouldn't have to do too much to get the
functionality you're looking for.

On Sat, Nov 4, 2023 at 8:18 PM Jerry Malcolm <te...@malcolms.com> wrote:

> My support team needs to be able to log in to our site as various users
> (on behalf of...) to be able to see exactly what they are seeing since
> roles, access groups, history is different for different users.  I would
> like to implement an admin password where I can log in as any userId
> with this password.  I totally realize the security risks involved in
> this.  But I am handling the security risks with additional
> authorizations.  I simply need to make every user have two passwords...
> their real personal password, and the admin password.  The only
> alternative I have right now is to save off the user's password hash in
> the USERS table, replace it with my password hash, then restore the
> user's original password when I'm done.  I'm not thrilled with that
> solution first because it's a pain and error prone, and also because the
> user can no longer log in while their password is replaced with my
> password.
>
>   I figure this function is buried in the authenticator code somewhere.
> But I'd first like to see if anybody has done anything like this
> already.  If not, could somebody point me in the right direction to the
> tomcat source file that I'm going to need to modify and also what's
> involved in making authentication use my updated class instead of the
> default.
>
> Suggestions?
>
> Thx
>
> Jerry
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>

-- 
Thanks,
Brian Wolfe
https://www.linkedin.com/in/brian-wolfe-3136425a/