For my JSF/TomEE application, I have a NoSQL database with users and roles that specifies how users can access resources (basically, IDs in a url parameter) either read-only or write.
I want to implement security and this post gave me some ideas but I am keen to try a 3rd party library - probably Shiro or PicketLink. The rule is that users will authenticate themselves with a client certificate, and if that is not provided, they will be authenticated as a default guest user.
Surprisingly, I am having a bit of trouble finding some information on how to do this in Shiro, it doesn't look straight forward. It is a bit of a surprise to me that there is nothing "out of the box" in Shiro to implement client certificate authentication.
So I think I have to create a Realm to "connect" Shiro with my database. Then I read I might need to extend org.apache.shiro.authc.UsernamePasswordToken
to read the certificate and pass it to Shiro. Then I suppose I have to restrict access to content in JSF xhtml pages (using the rendered
attribute for example) and I suppose that even in all methods of the Named
Managed beans I will need to check the permissions.
Also, It is not clear to me how I can assign the guest user when a certificate is not provided, since apparently it is TomEE the one who validates the client, so if no certificate is provided, my code will not get executed to assign the guest user. I could open two different ports in TomEE, but then the access will not be unified, since I want to treat the guest user uniformely, as any other user in the system. How can this be done?
Is this implemented in a easier way in PicketLink? (which is also better prepared for JSF)
OK, it took me a while and a lot of research, so I will summarise my findings dramatically. I documented everything but do not want to create a book chapter.
So I decided to go with Shiro, and everything I describe works and can be done. This X509certificate project for Shiro was quite useful. Basically, you need to implement a Realm overriding two methods (one for authentication and another for authorisation) - there is a class to extend in the code I mentioned before.
The distiction of a user not providing a cert can be done in the Shiro Filter, so when no token (certificate) is provided, one can be created on the fly or read from a keystore.
For restricting access in JSF there are some shiro tags that can help, no need to use rendered
. I have checked permissions also in the beans or other classes accessing the database. This works once the permissions have been established in the authorisation method.
The issue with Tomcat can be solved by using <Connector port="..." ClientAuth="want" ...
which will ask for a certificate but will not stop the user if no certificate is provided.