Updating roles in Tomcat from appserver in a REST applicatio

Posted by fredhamelin on 24-Apr-2015 12:44

Hi,

I am trying to update the Tomcat roles of a user that is already authenticated and can't find how to do this.

I need the user to only have access to POST to a specific url when he firsts logs in. I managed to do this by modifying intercept-url in my appSecurity-form-oerealm.xml file. The problem is I want to add roles after the POST to give him access to other resources. The only way I found to specify roles to Tomcat is by using the GetAttribute function in the HybridRealm class but it only gets called once when the user logs in.

Is there a way to send new roles to Tomcat in the response or something similar that could solve my problem?

Posted by Michael Jacobs on 28-Apr-2015 04:49

Hi Fred,

I've done some extra digging into Spring Security's RunAs functionality ( by reading source code ).  It appears that RunAs occurs AFTER the initial client Authentication phase is complete and just before the URL Authorization occurs.  Once the URL Authorization operation completes the RunAs restores the client's original token.  It will do this on each request.

This might be a good strategy for situations where an authenticated user's is temporarily elevated to execute a single REST resource, but it doesn't look like a good fit for denying all access until the account's password is changed.   It probably would not work well for the times you lock the account due to exceeding failed password limits or for handling 'forgotten password' situations.

Just my thought, but it also may not be usable if/when a different source ( or multiple sources ) of user accounts is used.

Another approach is to use the standard Spring Security account states (expired and/or locked) as intended.   Consider this scenario:

a) The client's account reaches maximum password age and during the next Authentication the OERealm server class returns the 'expired' state, which will fail the login and block the user from all of the REST resources

b) The client, seeing a 'expired' error could then login again, using the same credentials, to a 2nd REST service (in the same web application) supporting the 'forcepassword' resource.  That 2nd REST service uses a 2nd OERealm server class where it validates the user's old password and returns only the ROLE that allows it to execute the 'forcepassword' resource.  This would probably be a 'HTTP BASIC' model since you only need to access a single resource and its not worth establishing a second client session.

c) Once the 'forcepassword' completes, the user account's  password age can then be reset.  

d) The client - successfully completing the 'forcepassword' can then transparently login using the new password, which the OERealm server class passes and returns the ROLEs needed to access the full range of REST resources.

This basic pattern could also be used for handling safely 'forgotten password' situations safely.

My question at this point is can my client code differentiate between 'failed password", 'expired password', and 'password lockout' and do the right type of client interaction.   This is what I'll look at next.

Cheers,

Mike J.

All Replies

Posted by Peter Judge on 24-Apr-2015 12:49

I don't believe you can update roles after login.
 
-- peter
 
[collapse]
From: fredhamelin [mailto:bounce-fredhamelin@community.progress.com]
Sent: Friday, 24 April, 2015 13:45
To: TU.OE.Development@community.progress.com
Subject: [Technical Users - OE Development] Updating roles in Tomcat from appserver in a REST application
 
Thread created by fredhamelin

Hi,

I am trying to update the Tomcat roles of a user that is already authenticated and can't find how to do this.

I need the user to only have access to POST to a specific url when he firsts logs in. I managed to do this by modifying intercept-url in my appSecurity-form-oerealm.xml file. The problem is I want to add roles after the POST to give him access to other resources. The only way I found to specify roles to Tomcat is by using the GetAttribute function in the HybridRealm class but it only gets called once when the user logs in.

Is there a way to send new roles to Tomcat in the response or something similar that could solve my problem?

Stop receiving emails on this subject.

Flag this post as spam/abuse.

[/collapse]

Posted by Irfan on 24-Apr-2015 13:03

The roles and urls cannot be modified once you have started the server, you have to configure it accordingly. intercept-url is the only option to restrict a user/role based on the URL pattern. And this cannot be changed dynamically

Posted by Michael Jacobs on 24-Apr-2015 13:04

Hi Fred,
Spring Security is like using the Client-Principal in an OpenEdge application - once the Spring security token ( that holds the list of role they were granted) is created at login time, the list of roles is now fixed until the user's session is ended.

 Most often the <intercept-url> rule for the session login's POST operation is open for use by any connected client.  The <intercept-url> rules for the REST service's remaining restricted URL spaces can be assigned to one or more Roles according to your security model you are implementing.

I have seen some systems employ the concept of "assigned' versus 'active' privileges/roles where the 'active' list is assigned at user login time and the 'assigned' can be incrementally added later on an as-needed basis.  But I do not believe that Spring Security supports such a capability ( at least not without doing a bunch of custom Spring Security modules ).

Would you mind expanding on your use-case and why granting additional roles is necessary after a login session is started?

Mike J.

[collapse]
From: fredhamelin <bounce-fredhamelin@community.progress.com>
Reply-To: "TU.OE.Development@community.progress.com" <TU.OE.Development@community.progress.com>
Date: Friday, April 24, 2015 at 1:45 PM
To: "TU.OE.Development@community.progress.com" <TU.OE.Development@community.progress.com>
Subject: [Technical Users - OE Development] Updating roles in Tomcat from appserver in a REST application

Thread created by fredhamelin

Hi,

I am trying to update the Tomcat roles of a user that is already authenticated and can't find how to do this.

I need the user to only have access to POST to a specific url when he firsts logs in. I managed to do this by modifying intercept-url in my appSecurity-form-oerealm.xml file. The problem is I want to add roles after the POST to give him access to other resources. The only way I found to specify roles to Tomcat is by using the GetAttribute function in the HybridRealm class but it only gets called once when the user logs in.

Is there a way to send new roles to Tomcat in the response or something similar that could solve my problem?

Stop receiving emails on this subject.

Flag this post as spam/abuse.

[/collapse]

Posted by fredhamelin on 24-Apr-2015 13:22

In some cases, I want the user to update his information and password before having access to other resources. The url to post this information is currently accessible to every authenticated user and I added a new group to give access to /rest/** resources. The problem right now is that even after posting their updated information, users can't access other resources because I did not find a way to give access to the group after the login.

Posted by Michael Jacobs on 24-Apr-2015 16:35

Hi Fred,

Thank you for expanding on your use case.  I now see where you are heading.  While I do not have a definitive solution there may be some [slim] opportunities that could be explored.   I would recommend holding onto something solid for this next part...  (some small attempt at humor)

Spring Security does have a "Run-As" feature that I've not personally tried before because I didn't have a use-case to test it against.  The basis is that it can "temporarily" execute with an alternate security token, which I assume can mean alternate roles.   Not for the novice or faint of heart.

Spring Security also allows you to divide your /rest/... URL space into what amounts to separate security zones, complete with different configurations for the security tokens and their roles.  This may be closer to meeting what you want to accomplish, but would need some serious tinkering with the configuration to see if it was a candidate or not.  

I'll ponder on this some more over the weekend and see if anything else comes to mind that will help.

Nice question!

Mike J.

Posted by fredhamelin on 27-Apr-2015 09:29

Hi Mike,

I looked at the "Run-as" feature and it seems to do what I'm looking for. From what I understand, I need a class that implements the RunAsManager interface and a class that extends the RunAsImplAuthenticationProvider class. The problem is I don't know how the connection to the appserver is made. Is there some documentation about the classes in the restoe.jar file that I could use to know what each class does ?

Thanks!

Posted by Michael Jacobs on 28-Apr-2015 04:49

Hi Fred,

I've done some extra digging into Spring Security's RunAs functionality ( by reading source code ).  It appears that RunAs occurs AFTER the initial client Authentication phase is complete and just before the URL Authorization occurs.  Once the URL Authorization operation completes the RunAs restores the client's original token.  It will do this on each request.

This might be a good strategy for situations where an authenticated user's is temporarily elevated to execute a single REST resource, but it doesn't look like a good fit for denying all access until the account's password is changed.   It probably would not work well for the times you lock the account due to exceeding failed password limits or for handling 'forgotten password' situations.

Just my thought, but it also may not be usable if/when a different source ( or multiple sources ) of user accounts is used.

Another approach is to use the standard Spring Security account states (expired and/or locked) as intended.   Consider this scenario:

a) The client's account reaches maximum password age and during the next Authentication the OERealm server class returns the 'expired' state, which will fail the login and block the user from all of the REST resources

b) The client, seeing a 'expired' error could then login again, using the same credentials, to a 2nd REST service (in the same web application) supporting the 'forcepassword' resource.  That 2nd REST service uses a 2nd OERealm server class where it validates the user's old password and returns only the ROLE that allows it to execute the 'forcepassword' resource.  This would probably be a 'HTTP BASIC' model since you only need to access a single resource and its not worth establishing a second client session.

c) Once the 'forcepassword' completes, the user account's  password age can then be reset.  

d) The client - successfully completing the 'forcepassword' can then transparently login using the new password, which the OERealm server class passes and returns the ROLEs needed to access the full range of REST resources.

This basic pattern could also be used for handling safely 'forgotten password' situations safely.

My question at this point is can my client code differentiate between 'failed password", 'expired password', and 'password lockout' and do the right type of client interaction.   This is what I'll look at next.

Cheers,

Mike J.

Posted by fredhamelin on 28-Apr-2015 14:08

Hi Mike,

I managed to make it work by using your last solution with the ATTR_EXPIRED attribute and the second REST service with basic authentication.

To provide the client with a way of knowing if it is a failed password or an expired password, I extended the com.progress.rest.security.OEAuthnFailHandler class to return a JSON response based on the exception sent to the onAuthenticationFailure() method.

Thanks a lot for the help!

Posted by Michael Jacobs on 28-Apr-2015 14:54

Fantastic!

I was looking in precisely the same location, but were a lot faster than I was.

I was happy to be of assistance.

Mike J.

This thread is closed