Instant ACLs with Zend Framework 2

18,071 views
17,670 views

Published on

Slides of my Zend Framework Day 2014 presentation in Turin (Italy) about ZF2 authentication and authorization.

Published in: Technology
3 Comments
20 Likes
Statistics
Notes
  • I'm trying to setup assertion. How to do it?
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • @raskiv yes, exactly. We don't need to explicitly add zfc-user dependence into our composer.json, because it's already requested by zfc-user-doctrine-orm (take a look inside 'require' block here https://github.com/ZF-Commons/ZfcUserDoctrineORM/blob/master/composer.json). Executing 'php composer.phar update' we get all dependencies recursively, so zfc-user will be downloaded automatically.

    Stefano
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Hi,
    Looks like in your setup composer does not install 'zf-commons/zfc-user' package, as oppose to an example here:
    http://samminds.com/2013/03/zfcuser-bjyauthorize-and-doctrine-working-together/

    Does it mean that with 'zf-commons/zfc-user-doctrine-orm' we do not need to specify 'zf-commons/zfc-user' for composer ?

    Thanks.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
18,071
On SlideShare
0
From Embeds
0
Number of Embeds
343
Actions
Shares
0
Downloads
356
Comments
3
Likes
20
Embeds 0
No embeds

No notes for slide

Instant ACLs with Zend Framework 2

  1. 1. Instant ACLs with Zend Framework 2 Zend Framework Day – Turin, Italy – 07/02/2014
  2. 2. @stefanovalle
  3. 3. http://www.mvlabs.it/
  4. 4. http://friuli.grusp.org/
  5. 5. AUTHENTICATION AUTHORIZATION 5
  6. 6. Two step process
  7. 7. Two step process WHO WHAT
  8. 8. Two step process WHO Authentication “a process that ensures and confirms a user’s identity” WHAT Definitions from http://www.techopedia.com
  9. 9. Two step process WHO WHAT Authentication “a process that ensures and confirms a user’s identity” Authorization “a security mechanism used to determine user/client privileges or access levels related to system resources” Definitions from http://www.techopedia.com
  10. 10. 11
  11. 11. In ZF2 WHO Zend/Authentication
  12. 12. In ZF2 WHO Zend/Authentication Authenticate against: • DB table • LDAP • HTTP • And more…
  13. 13. In ZF2 WHAT Zend/Permissions/Acl Zend/Permissions/Rbac
  14. 14. In ZF2 WHAT Zend/Permissions/Acl Zend/Permissions/Rbac Role Permission Identity Resource
  15. 15. SEEMS TOUGH…
  16. 16. JUST AS IT SHOULD!
  17. 17. CONSEQUENCES COULD BE UNDERESTIMATED
  18. 18. How does ZF2 help? 19
  19. 19. ‘NUFF TALK. TIME FOR ACTION…
  20. 20. We need to add/edit conferences through a restricted area 1ST NEED
  21. 21. THE ADMINISTRATOR NEEDS TO BE RECOGNIZED
  22. 22. THE ADMINISTRATOR NEEDS TO BE RECOGNIZED IDENTIFIED
  23. 23. HEAD TO OFFICIAL MODULES’ WEBSITE
  24. 24. OH, LOOK WHAT WE JUST GOT!
  25. 25. Installing and enabling ZfcUser // composer.json "require": { "zf-commons/zfc-user-doctrine-orm": "0.1.*" } 28
  26. 26. Installing and enabling ZfcUser // composer.json "require": { "zf-commons/zfc-user-doctrine-orm": "0.1.*" } let’s suppose we use the Doctrine ORM 29
  27. 27. Installing and enabling ZfcUser // composer.json "require": { "zf-commons/zfc-user-doctrine-orm": "0.1.*" } // config/application.config.php <?php return array( 'modules' => array( // ... 'ZfcBase', 'ZfcUser', 'ZfcUserDoctrineORM', ), ); 30
  28. 28. Back to our user… 31
  29. 29. How shall we represent him?
  30. 30. We need a class class Systemuser { private $id; private $name; private $city; private $birthday; private $username; private $password; }
  31. 31. With some mandatory fields class Systemuser { private $id; private $name; private $city; private $birthday; private $username; private $password; }
  32. 32. Implementing an interface class Systemuser implements ZfcUserEntityUserInterface { private $id; private $name; private $city; private $birthday; private $username; private $password; }
  33. 33. Let’s configure ZfcUser // config/autoload/zfcuser.global.php /** ZfcUser Configuration */ $settings = array( /** User Model Entity Class */ 'user_entity_class' => 'ApplicationEntitySystemuser', /** Start configuration for ZfcUserDoctrineORM */ 'enable_default_entities' => false, ); 36
  34. 34. Yay, here’s our working login form! 37
  35. 35. Yay, here’s our working login form! Available at: http://myaddress/user/login 38
  36. 36. Yay, it works! 39
  37. 37. ZfcUser also allows to: • • • • • 40 Customize login form Customize User entity fields Quickly implement a registration form Interact with either Zend/DB or Doctrine out of the box Do much more stuff…
  38. 38. ZfcUser also allows to: • • • • • 41 Customize login form Customize User entity fields Quickly implement a registration form Interact with either Zend/DB or Doctrine out of the box Do much more stuff…
  39. 39. Remember the two steps? WHO WHAT
  40. 40. Remember the two steps? WHO WHAT
  41. 41. We need an admin panel! 44
  42. 42. We need an admin panel! Welcome ZfcAdmin! provides a ready to use /admin route 45
  43. 43. hubme.in has an admin panel!
  44. 44. hubme.in has an admin panel!
  45. 45. Are we done yet? 48
  46. 46. What if a malicious user…
  47. 47. What if a malicious user…
  48. 48. What if a malicious user… …hits this url: http://myawesomewebsite/admin/conferences
  49. 49. What if a malicious user… …hits this url: http://myawesomewebsite/admin/conferences accessible to everyone!
  50. 50. What if a malicious user… …hits this url: http://myawesomewebsite/admin/conferences nothing’s protecting our private area
  51. 51. What if a malicious user… …hits this url: http://myawesomewebsite/admin/conferences nothing’s protecting our private area Login form could be bypassed!
  52. 52. No worries! /* * On each action */ <?php public function indexAction() { if (!$this->zfcUserAuthentication()->hasIdentity()) { return $this->redirect()->toRoute('home'); } } 55
  53. 53. No worries! /* * On each action */ <?php public function indexAction() { if (!$this->zfcUserAuthentication()->hasIdentity()) { return $this->redirect()->toRoute('home'); } } 56 in EACH action of EACH controller
  54. 54. WHAAAT?
  55. 55. IN EACH ACTION???
  56. 56. SOMEONE HELP US!
  57. 57. ZENDPERMISSIONSACL
  58. 58. Remember? There were two steps… WHO WHAT
  59. 59. Using Zend/Permissions/Acl <?php use ZendPermissionsAclAcl; use ZendPermissionsAclRoleGenericRole as Role; use ZendPermissionsAclResourceGenericResource as Resource; $acl = new Acl(); $acl->addRole(new Role('guest')) ->addRole(new Role('admin')); $acl->addResource(new $acl->addResource(new $acl->addResource(new $acl->addResource(new $acl->allow('guest', $acl->allow('admin', $acl->allow('admin', $acl->allow('admin', 62 Resource('someResource')); Resource('adminarea')); Resource('adminconferencearea')); Resource('adminsettingsarea')); 'someResource'); 'adminarea'); 'adminconferencearea '); 'adminsettingsarea ');
  60. 60. Welcome BjyAuthorize! … a facade for ZendPermissionsAcl that will ease its usage with modules and applications … From https://github.com/bjyoungblood/BjyAuthorize 63
  61. 61. Welcome BjyAuthorize! … a facade for ZendPermissionsAcl that will ease its usage with modules and applications … From https://github.com/bjyoungblood/BjyAuthorize 64
  62. 62. OUR EASIER WAY
  63. 63. How does it work? 66
  64. 64. Standard ZendMvc app workflow From https://github.com/bjyoungblood/BjyAuthorize 67
  65. 65. With BjyAuthorize enabled From https://github.com/bjyoungblood/BjyAuthorize 68
  66. 66. With BjyAuthorize enabled From https://github.com/bjyoungblood/BjyAuthorize 69
  67. 67. With BjyAuthorize enabled From https://github.com/bjyoungblood/BjyAuthorize 70
  68. 68. With BjyAuthorize enabled + control over resources From https://github.com/bjyoungblood/BjyAuthorize 71
  69. 69. Installing and enabling BjyAuthorize // composer.json "require": { "bjyoungblood/bjy-authorize": "1.4.*" } // config/application.config.php <?php return array( 'modules' => array( // ... 'BjyAuthorize', ), ); 72
  70. 70. Configuring BjyAuthorize // config/autoload/bjyauthorize.global return array( 'bjyauthorize' => array( 'default_role' => 'guest', 'identity_provider' => 'BjyAuthorizeProviderIdentityAuthenticationIdentityProvider', 'role_providers' => array( 'BjyAuthorizeProviderRoleConfig' => array( 'guest' => array(), 'admin' => array(), ), ), ), ); 73
  71. 71. Configuring BjyAuthorize // config/autoload/bjyauthorize.global return array( 'bjyauthorize' => array( A new concept: the Role 'default_role' => 'guest', 'identity_provider' => 'BjyAuthorizeProviderIdentityAuthenticationIdentityProvider', 'role_providers' => array( 'BjyAuthorizeProviderRoleConfig' => array( 'guest' => array(), 'admin' => array(), ), ), ), ); 74
  72. 72. Guards on routes http://myawesomewebsite/ Allowed to all users 75
  73. 73. Guards on routes http://myawesomewebsite/ Allowed to all users http://myawesomewebsite/admin/... Restricted area! For admins only 76
  74. 74. Guards on controller actions class ConferencesController { public function listAction() { // code... } public function manageAction() { // code... } } 77
  75. 75. Guards on controller actions class ConferencesController { public function listAction() { // code... } Allowed public function manageAction() { // code... } } 78 to all users
  76. 76. Guards on controller actions class ConferencesController { public function listAction() { // code... } Allowed to all users public function manageAction() { // code... } } 79 Restricted area! For admins only
  77. 77. Guards on controller actions array( 'controller' => 'ZfcAdminControllerAdminController', 'roles' => array('admin') ) 80
  78. 78. Where should guards be placed? 81
  79. 79. Inside each module configuration // module/Conferences/config/module.config.php return array( 'bjyauthorize' => array( 'guards' => array( 'BjyAuthorizeGuardController' => array( //... ), ), ), 82
  80. 80. Inside each module configuration // module/Conferences/config/module.config.php return array( 'bjyauthorize' => array( Taking advantage of ZF2 configuration merge 'BjyAuthorizeGuardController' => array( 'guards' => array( //... ), ), ), 83
  81. 81. It works!
  82. 82. It works! User could be redirected to whatever url we want
  83. 83. Dude, forgot to tell ya! …we got 2 fellas! 2ND NEED
  84. 84. Two different roles The reader 87
  85. 85. Two different roles The reader 88
  86. 86. Two different roles The reader 89 The editor
  87. 87. Two different roles Can only view conference info The reader 90 Can view conferences + create, edit and delete info The editor
  88. 88. What we want Only editor should see these icons
  89. 89. Until now… 'bjyauthorize' => array( // ... 'role_providers' => array( 'BjyAuthorizeProviderRoleConfig' => array( 'guest' => array(), 'admin' => array(), ), ), ) Static role list 93
  90. 90. Until now… 'bjyauthorize' => array( // ... 'role_providers' => array( 'BjyAuthorizeProviderRoleConfig' => array( 'guest' => array(), 'admin' => array(), ), ), ) More flexibility wouldn’t hurt… 94
  91. 91. BjyAuthorize config changes // config/autoload/bjyauthorize.global return array( 'bjyauthorize' => array( 'role_providers' => array( 'BjyAuthorizeProviderRoleObjectRepositoryProvider' => array( 'role_entity_class' => 'ApplicationEntityRole', 'object_manager' => 'doctrine.entity_manager.orm_default', ), ), ), ); From array to class (persisted on db) 95
  92. 92. Let’s map the actions
  93. 93. New concept: the Resource
  94. 94. something
  95. 95. something upon which someone
  96. 96. something upon which someone could perform an action
  97. 97. ENTITY IDENTITY / ROLE PRIVILEGE
  98. 98. On BjyAuthorize… 'resource_providers' => array( 'BjyAuthorizeProviderResourceConfig' => array( 'Conference' => array(), ), ), 'rule_providers' => array( 'BjyAuthorizeProviderRuleConfig' => array( 'allow' => array( // allow editors to edit conferences array(array('editor'), 'Conference', array('edit')), ), ), 102
  99. 99. On views… //Conferences/view/…/index.phtml <?php if ($this->isAllowed($event, 'edit')) { ?> <a href="someurl">Remove</a><br /> <a href="someurl">Edit</a> <?php } ?> 103
  100. 100. Views, routes and controllers are safe 104
  101. 101. Views, routes and controllers are safe Is this enough? 105
  102. 102. Another controller, another action //Conferences/Controller/AnotherAdminController.php class AnotherAdminController extends AbstractActionController { public function someCrazyAction() { //... $this->conferenceService->updateConference($myConference); } } What prevents this? 106
  103. 103. 107 SERVICE CONTROLLER ROUTE Choose your protection level
  104. 104. Conference service //Conferences/Service/ConferenceService.php namespace ConferencesService; class ConferenceService { public function getConference($id) { ... } public function getConferenceList($someCriteria) { ... } public function updateConference($myConf) { ... } public function deleteConference($myConf) { ... } } 108
  105. 105. Conference service //Conferences/Service/ConferenceService.php namespace ConferencesService; class ConferenceService { public function getConference($id) { ... } public function getConferenceList($someCriteria) { ... } public function updateConference($myConf) { ... } public function deleteConference($myConf) { ... } } Only to allowed users! 109
  106. 106. Let’s inject the Authorize class //Conferences/Service/ConferenceServiceFactory.php namespace ConferencesService; class ConferenceServiceFactory implements FactoryInterface { public function createService(ServiceLocatorInterface $serviceLocator) { //... $authorize = $serviceLocator->get('BjyAuthorizeServiceAuthorize'); return new ConferenceService(..., $authorize); } } 110
  107. 107. Updated conference service //Conferences/Service/ConferenceService.php namespace ConferencesService; class ConferenceService { //... public function updateConference($myConf) { if (!$this->authorize->isAllowed($myConf, 'edit')) { throw new UnAuthorizedException(); } // other code... } // the same for deleteConference method } 111
  108. 108. 112 SERVICE CONTROLLER ROUTE Now our service is secured
  109. 109. We’ll outsource the management of foreign conferences 3RD NEED
  110. 110. Based on their country
  111. 111. How database changes class Systemuser { //... private $country; } class Conference { //... private $country; } 116
  112. 112. Create an Assertion use ZendPermissionsAclAssertionAssertionInterface; class CheckUserCountry implements AssertionInterface { // ... public function assert(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null) { // ... } } 117
  113. 113. Create an Assertion use ZendPermissionsAclAssertionAssertionInterface; class CheckUserCountry implements AssertionInterface { // ... public function assert(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null) { return $resource->getCountry() == $this->loggedUser->getCountry(); } } 118
  114. 114. Create an Assertion use ZendPermissionsAclAssertionAssertionInterface; class CheckUserCountry implements AssertionInterface { // ... Injected through constructor public function assert(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null) { return $resource->getCountry() == $this->loggedUser->getCountry(); } } 119
  115. 115. Create an Assertion use ZendPermissionsAclAssertionAssertionInterface; class CheckUserCountry implements AssertionInterface { // ... public function assert(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null) { return $resource->getCountry() == $this->loggedUser->getCountry(); } } 120 1 LoC… AWESOME!!
  116. 116. Update rule with the new assertion 'rule_providers' => array( 'BjyAuthorizeProviderRuleConfig' => array( 'allow' => array( // role check through assertion array(array('editor'), 'Conference', array('edit'), 'assertion.CheckUserCountry'), ), ), 121
  117. 117. The reader 122
  118. 118. The reader The editor 123
  119. 119. In the same way we could: • • • 124 Restrict access to user owned onferences only or conferences owned by a group the user is belonging to …and much more!
  120. 120. Cool. How'bout the admin menu though? 4TH NEED
  121. 121. Navigation menu 126
  122. 122. Configure Zend/Navigation // module/Conferences/config/module.config.php return array( 'navigation' => array( 'admin' => array( 'conferences' => array( 'label' => 'Conferences', 'route' => 'zfcadmin/conferences', 'resource' => 'Conference', 'privilege' => 'view', ), ), ), ), ); 127
  123. 123. Configure Zend/Navigation // module/Settings/config/module.config.php return array( 'navigation' => array( 'admin' => array( 'settings' => array( 'label' => 'Settings', 'route' => 'zfcadmin/settings', 'resource' => 'Setting', 'privilege' => 'view', ), ), ), ), ); 128
  124. 124. How menu looks like for admins
  125. 125. How menu looks like for other users
  126. 126. FINAL NOTES
  127. 127. PLUGGABLE COMPONENTS
  128. 128. PLUGGABLE COMPONENTS CLEAN ARCHITECTURE
  129. 129. PLUGGABLE COMPONENTS CLEAN ARCHITECTURE COMPLEX ACL LOGIC IN A FEW MINUTES
  130. 130. Thank you for your attention! Stefano Valle @stefanovalle s.valle@mvassociati.it
  131. 131. Questions? Stefano Valle @stefanovalle s.valle@mvassociati.it
  132. 132. Photo Credits From Flickr: http://www.flickr.com/photos/cbpphotos/8652042987 http://www.flickr.com/photos/disa4ever/9409743179 http://www.flickr.com/photos/ben_salter/6169305845 http://www.flickr.com/photos/elzey/3481161467 http://www.flickr.com/photos/morris278/8022505933 A-Team members’ photos: http://5gta.com/gta-5-info/gta-5-the-a-team-similarities.html/ http://www.legendarytv.com/the_a-team/the_a-team_lance_legault.asp http://www.fanpop.com/clubs/the-a-team/images http://dwightschultz.freeforums.org/dwight-photo-s-t8.html http://docmanhattan.blogspot.it/2010/10/vita-mort-immortalita-e-miracoli-di-mr.html http://www.starsky-iom.com/forum/viewtopic.php?f=8&t=58 http://www.thea-teamonline.com/ And others form iStockPhoto 137

×