Thursday, January 23, 2014

Csn modules. How everything works together?

This is a draft version of the post. If I have time I will improve it.
When I think about our application I think for it like a factory. A company producing something. In our case data. So this is how it looks:

fig. 1
Every controller is a building. Inside of each controller we have actions (methods=functions). Think about the actions like machines. They can do different things.
Everything is OK, but we don't have control who is using our machines. We want to know who is the user. We want to control the access. In order to do so, we need Authentication and Authorization systems.
CsnUser provides us with Authentication and Registration system. CsnAuthorization provides us with Authorization.
1) Lets talk about the Authentication system. It is base on the PHP sessions. On its turn the session in PHP rely on cookies, but not always. The session can exist without cookies. Cookies is a server technology. It shows up on the computer of the client (browser), but it is a server technology. Since http is a stateless protocol, the server don't remember the users. This is the reason the server asks the browser to save cookies on the clients machine (browser). In the case of PHP the variable is called PHPSESSID. Lets see if we can see this.
On the screenshot above we see the Zend Skeleton application just started. The Csn modules have been installed. The session gets started automatically.
I will take advantage of the fact that my server is on the same computer so lets see how the session looks on the clients browser and the server. In the screenshot above you can see the cookie "PHPSESSID" and it value. A file with the same name as the PHPSESSID value has been created in the temp folder on the server "C:\WINDOWS\Temp\sess_jnd4lc08v70jq4ld79ouinu4n5". "C:\WINDOWS\Temp" is the default temp folder wor Windows. The session can be stored in a database. All we need is just to prepare a handler in PHP. I usually do that. But for the purposes of this blog post I will continue using a file to store the session data. So there is a cookie called "PHPSESSID" set on the client computer. Is value determent the unique identifier (name of the session file) on the server where all the session variables get serialized and saved. I believe they are serialized.

In the screenshot above we see the content of the session on the server. The name of the cookie "PHPSESSID" can be changed in the php.ini settings. There we have control on the expiration time as well.

3-4 hours later lets see if the session id is the same. Another words lets check the value of PHPSESSID cookie in the browser and the corresponding file on the server. I will refresh the page http://localhost:10127/.
The cookie stays there and the value is not changed PHPSESSID = jnd4lc08v70jq4ld79ouinu4n5

The next thing we will do is log in and see how this will change the value of the session file.



The content of the session file has been changed:



__ZF|a:1:{s:20:"_REQUEST_ACCESS_TIME";d:1390316716.3404560089111328125;}Zend_Auth|C:23:"Zend\Stdlib\ArrayObject":145:{a:4:{s:7:"storage";a:1:{s:7:"storage";a:1:{s:2:"id";i:1;}}s:4:"flag";i:2;s:13:"iteratorClass";s:13:"ArrayIterator";s:19:"protectedProperties";N;}}

The information about the user was retrieved from the DB and saved in the session. So it can be easily accessed. The magic happens in the loginAction

The controller which takes care of the Authentication is a controller like every other. Everybody should have access to it in order to log in. I will try to explain how this works in the real life.

Whoever enters our domain (the green circle) gets a session ID. A cookie PHPSESSID gets set for the domain http://localhost:10127/. The server keeps a corresponding file or database record. Variables can be saved on the server about the session. The module "CsnUser" and its controller "IndexController" "loginAction" takes care of that. Another words our server attaches an identification card to every visitor of our domain. The loginAction looks to me like a desk of the security guards. Everywhere in the application we can call the "Zend\Authentication\AuthenticationService"
This service will provide us with the identity information. This is a security guard who checks the credential and sets the identity. I would imagine the stranger visiting our domain (site) going to Authentication controller and asking the guard: "Please, I want to be identified. My username and password are such and such. The guard goes in the back to the database room and checks for such username and password. If there is a match it retrieve the information from the database. After that the information gets written by the guard on a cart that stays on the guards desk (session). There is an unique ID attached to every visitor (the session ID). The visitor carries around his/her ID. The very same ID is written on the card that lies on the guards desk. This is how the correlation between the user and the card has been made. The session will expire in a give period of time. Usually after 22 minutes by default. Another words if the visitor doesn't show up again in our domain within 22 minutes the guard will destroy the card with the information about the visitor. The session will expire.

Once we can identify the visitor lets control the access to the controllers and the actions. This is done using so called ACL = Access Control List. ACL deals with 3 terms: Resources, Roles, Privileges. It looks like a human written list for access. It describes what role has access to what resource. The module CsnAuthorization takes care of that. The acl.global.php.dist is a good example.In the module CsnAuthorization we create a guard that takes care of everyone who trys to get to a Controller = Building in application. It is an event listener defined in the Module.php of the CsnAuthorization module.

What it does is the following: 
1) Calls the Authentication Service. If we continue the comparison with the factory it calls the guards taking of the Authentication asking them "Do you know this guy?". If they don't know him, he will be treated as "guest". If they know him we get the role of the visitor.

2) Asks the router: "Where are you going?" Give me the Controller = Resource and the action = privilege.

3) Calls the girl in the office and asks her to check the Access Control List. The question is: "Please check if a visitor with the given role is allowed to access the Resource and has the privilege to execute the given action."

After doing log out the cookie was replaced by another one "sess_pm2jiqtluiqfb4vfeqcodsdrv4" and this is the content:
__ZF|a:1:{s:20:"_REQUEST_ACCESS_TIME";d:1390322840.41504192352294921875;}Zend_Auth|C:23:"Zend\Stdlib\ArrayObject":112:{a:4:{s:7:"storage";a:0:{}s:4:"flag";i:2;s:13:"iteratorClass";s:13:"ArrayIterator";s:19:"protectedProperties";N;}}


Our guard in AclAuthorizaton collects data from 3 sources as I described above. You can see this in the picture. You can see the code snippet bellow.

There is a module for navigation CsnNavigation
It is an Object Oriented approach gibing us better control from inside of the application. But I think it becomes even more useful when it is combined with the ACL. We have done exactly this in the module CsnAclNavigation.
Lets take a look how it works. I will compare it again with a real life example from our factory.

To see how that works you can take a look the code.
Or you can see the snippet bellow: