NemID challenges as a module through webservices
As I mentioned in an earlier post Thoughts about NemID versus Payment gatways, my setup is based on webservices. In this article I will elaborate on how it works and some of the thoughts, troubles, challenges behind my solution.
In my current job position I work at Tangora Software A/S, a standard proprietary CMS, but the integrations to the system is based on SOAP webservices (webservices) and makes it easy to create outside services to interact with the system. There are several modules in the systems and nearly all modules have one or more ability to attach a webservice to it. On of those modules is the page module og the page type HTML. The HTML page type is a simple page where you do your own HTML, turn of default site layout, use WinHTTP, iFrame and attach a webservice. The HTML page is a "dumb" page and it takes any kind of request; be it a GET, POST or COOKIE. Besides the HTML page there's another important module is in play and that's the external login module. Which in this case supplies my with a username and password form for login on the user to the website. In Tangora, the only way to validate a user and create a login session is through this module. But it is not limited to validate against users created in the system, this module can handle webservice calls to external sources of users. One example could be a single sign on service onto a companys intranet with the same username the user uses for the company domain validated through Active Directory (AD). The login form gets the request with the username of ther user and a time based token, this information is passed through the form to the webservice validation which validates the token and looks up the user in the AD. If both information checks out a XML document is returned with user information and the CMS logs the user on, with the data supplied from the external source. Now the modules are in play and we know what they can do, lets get on with the setup.
The NemID setup
If you're familier with NemID, you'll know that when you visit a private company website with NemID validation, you'll be greeted with the Java Applet, when that is conquered you'll need to supply your CPR once again and lastly the website will log you on. In a typical Tangora NemID solution we end up with four pages and the entire process is behind SSL.
First hurdle was to present the applet to the user. In all the examples from DanID, they are working with a regular ASP.Net webpage and they can manipulate it as they see fit. Because Tangora is a closed piece of software I do not have this option, but with the HTML page I can return custom HTML and present that to the user and the HTML is created in the webservice. I have a webservice method for creating the applet. Before creating the applet I need some parameters:
- A serial number from the customers company certificate supplied by DanID
- The password for the certificate.
- Which page the user should be redirected to after the user is done with the apple. Bullet one and two are for validating against DanIDs services that this customer can and are allowed to make NemID validations. If that is the case I create the HTML containing the applet markup and a hidden form for posting values to the next step. The design of the HTML is so "loose", that you can shape as you like with a few lines of CSS, which makes room for the customers designer to change the look of the HTML. The HTML also supplies the customer with standard links and guides for the user of the website to feel safe and familier with the process. When the user is done with the applet, the applet post the hidden form and some extra info, to the next step.
The CPR input
Because our customers are from the private sector, the applet cannot supply me with the users social security number (CPR), but instead give me a Personal IDentifications number (PID) or if it's a company the company number (CVR). Before I decide to present the user with the CPR input form I, fist need to take the posted variables from the applet and ask DanID what kind of user are we dealing with. If it is a company user, acting on the behalf of the company we call him MOCES and if it is a private user we call him POCES. MOCES do not need to re-input their CVR number they are justed passed through to the last step with the time based token. POCES need to suppliy their CPR number once again, just for the fun of it. The public sector does not have this hurdle. They can query for the CPR number by supplying the PID, all other have to ask the user for the CPR and then send the CPR and PID to DanID for validation in the next step. Because of this inconvenience and because we do not want to bother the user about this everytime he visits the site, I'm caching the CPR and PID in a ordely fashion, so I don't have to ask the user for the CPR number everythime, I can just look up the PID and get the CPR number and continue to the next step without the users notice it. Along with the caching I'm also creating a time based token which will be used in the last step.
The NemID Validation
Here I validate the users PID and CVR against DanID, if it fails go back a step and ask the user to input the CPR again, otherwise take the token and pass it to login form along with CPR number. The username has to be the CPR numer because this is known to user. The user does not know the PID, this is not disclosed to the public.
As you may remember my login form had a webservice attached for external validation. The form gets the posted request and and pass it through to the webservice and the request contained the CPR number and the time based token. The webservice takes the token and looks it up in the cache, if it hasn't expired yet and exists, the user is looked up based on the CPR number and a user XML document is created and returned to the website and the user will continue to the resticted area.
As and outsider this may not seem that advanced or complicated, but then again I have left out all the complications about how hard it is to work with DanID, the company behind NemID and how many hours I've spend on their "support" and Java version that no longer works with the NemID applet. Actually I had most of my problems when working with the test environment DanID has setup before a solution goes into production. Once my test environment was up and running it was easy to get a working prototype up and running and then begin to understanded what I needed to do, to create a webservice NemID module for Tangora. As I mentioned in a earlier post, my biggest challenge is when DanID releases a new NemID .Net package with new feature or corrections. Because I've made the solution they way I have, I have to get the source package from DanID, which they supply, and make my corrections and test before our customers can get the changes. this is time consuming and sometimes cumbersom. When the NemID application is starting up, it calls alot of external sources which are static. The creation of these static objects take a long time and can spell timeout in several occations. Well, at least that is what happened to me. Our NemID webservice is not used that often, so the webservice would return to idle state and releasing all of its resources. This would cause the next hit to be slow and maybe the next hit after that would then cause a timeout. To prevent this in an quick and dirty fashion I create a windows service with one purpose to keep this webservice active and alive. It will ping the NemID service every two hours. This keeps the webservice up and running smooth and no bad errors presented for the user. Adding new NemID service providers to my solution is quite easy now and takes less effort. Once the customer has been supplied with their company certificate I register it in the module and create the needed pages on the customers website to make it work and thats basically it.