I have been working through all the different spring security options when working with REST services and have hit a problem when trying to test the SPA hybridrealm features.
I have tried to produce the equivalent of the SPA example for BPM found in the samples folder.
Everything works ok apart from the fact no client principal object from spring security is passed across to the hybridrealm.cls on the appserver. Should one be created or should I create one myself and reset the information using SESSION:CURRENT-REQUEST-INFO:SetClientPrincipal().
When editing the OERealmUserDetails there is a property for the realmTokenFile. Is this the location of where a sealed client principal can be found. If so where should this be located. I have placed the file in various locations and always receive an error in the logs saying the file cannot be opened.
connectSPAClient - Error loading realm's ClientPrincipal: java.lang.Exception: Could not open file in classpath: /WEB-INF/oespaclient.cp
Any ideas anyone
The following is an except from developer notes regarding REST web application
OERealm support. It will provide the general development and runtime operations.
Hope this helps,
The development process is as follows:
1.Use the $DLC/bin/genspacp utility to create a sealed Client-Principal that represents a valid AppServer OERealm service interface client. You minimally supply the user-id, domain name, domain access code, and output file name to the utility and it outputs a binary file holding a sealed Client-Principal (ex: oerealm.cp). The domain name and domain access code correspond to the domain name and domain access codes that will be used in the AppServer OERealm service interface to validate clients. In this case
2.Copy the output file (oerealm.cp) from $DLC/bin/genspacp into the OE web application's WEB-INF/classes directory
3.The OERealmUserDetails configuration property "realmTokenFile" to contain the name of the file copied into the WEB-INF/classes directory ("oerealm.cp")
4.Add to the OERealm service interface the Client-Principal validation. This Client-Principal validation code may reside in the AppServer's Activate Procedure or as a step in each of the OERealm class's methods. The Client-Principal validation may use any of the normal validation types, but in this case the CLIENT-PRINCIPAL:VALIDATE-SEAL("domain-access-code") works well. If you do use CLIENT-PRINCIPAL:VALIDATE-SEAL(), store the domain-access-code in the encoded form "oech1::xxxxxxxxxx" as is used in other parts of the product. DO NOT STORE CLEAR TEXT DOMAIN ACCESS CODES IN YOUR APPLICATION
5.If the Client-Principal validation in the AppServer's OERealm service interface, return an error, but DO NOT return user account information.
The runtime process is as follows:
1.When the OE web application is loaded, the OERealmUserDetails object will look at its "realmTokenFile" property and if it is non-blank it will load the Client-Principal from the file you copied into its WEB-INF/classes directory. If the file load fails, an error will be logged but the web application will continue to run
2.When the OE web application performs a user authentication the OERealmUserDetails object will send its Client-Principal to the AppServer on each OERealm method request. If a Client-Principal was not loaded, one will not be sent to the AppServer (not having a Client-Principal is NOT and error)
3.When the OERealm service interface gets a method request operation, it will do the Client-Principal validation:
Doing the OERealm security work or not is really subject to how secure you want to keep your application's user account data. That is why we made it optional. If you are sure that no OpenEdge client on your network except BPM or REST can connect to your AppServer's OERealm api, then the OERealm security work is not going to make you any safer. If you have any doubts at all, then the safe course is to work out the OERealm security and use it.
But whether you use OERealm security or not does not affect what you are seeing in the logs. The integer value returned from the ValidateUser() method is interpreted as a unique ID associated with a physical user account in your application. The OERealm client in the REST service will interpret -1 (a non-positive #) as an error code indicating an account does not exist. If the account does not exist, then no Client-Principal is generated for it.
The positive ID returned by ValidateUser() is then passed by the OERealm client to subsequent methods that return account attributers or validate the client's password credential. The methods in the OERealm class simply uses the INPUT ID as a lookup reference to the physical user account to use in order to satisfy the client's request for information. You can see this demonstrated in the sample HybridRealm.cls file.
This entire process assumes that your user accounts can be uniquely identified with an INTEGER ID that can be used by multiple AppServer agents.
Thanks for the detailed reply.
That was a great help for deploying the sealed client principal to the correct location for testing.
I have a couple more problems that you may be able to help with.
When using the validateuser method based on the IHybridRealm interface it expects a userid to be returned (INTEGER). What makes use of this userid. I have tested with -1 and messages like the following appear in the logs
loadUserByUsername - Username load error for who@employee re: general error: org.springframework.security.core.userdetails.UsernameNotFoundException: User account not found
That's ok because for example I can return 1 (for testing) and nothing appears in the log but the REST service does not work and return any JSON data.
Step 1-3 all seem ok
Step 4 4 my hybridrealm class validates the client principal correctly.
Should all this OERealm security work with a simple business entity class or its it overkill. I would like to authenticate users based on the current userprofile table in our legacy application.
Thanks again for the reply. I had worked out that the non-positive number was used as an error code and this resulted in the error being recorded in the logs. I will take this further with a REST client to test the business entity methods. I think when I was testing via IE10 and received no results back from the REST service I assumed I needed to do more on the business entity class.
I'm basically testing out all the authentication methods so we have a better understanding how they all work. I will test these out with a mobile application rather than just the rest service now.
Thanks for all your help. It's been very useful.