Instant ACLs with Zend Framework 2

137
Zend Framework Day – Turin, Italy – 07/02/2014 Instant ACLs with Zend Framework 2

description

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

Transcript of Instant ACLs with Zend Framework 2

Page 1: Instant ACLs with Zend Framework 2

Zend Framework Day – Turin, Italy – 07/02/2014

Instant ACLswith Zend Framework 2

Page 2: Instant ACLs with Zend Framework 2

@stefanovalle

Page 3: Instant ACLs with Zend Framework 2

http://www.mvlabs.it/

Page 4: Instant ACLs with Zend Framework 2

http://friuli.grusp.org/

Page 5: Instant ACLs with Zend Framework 2

5

AUTHENTICATION AUTHORIZATION

Page 6: Instant ACLs with Zend Framework 2
Page 7: Instant ACLs with Zend Framework 2

Two step process

Page 8: Instant ACLs with Zend Framework 2

Two step process

WHO

WHAT

Page 9: Instant ACLs with Zend Framework 2

Two step process

WHO

WHAT

Authentication

Definitions from http://www.techopedia.com

“a process that ensures and confirmsa user’s identity”

Page 10: Instant ACLs with Zend Framework 2

Two step process

WHO

WHAT

Authentication

Definitions from http://www.techopedia.com

“a process that ensures and confirmsa user’s identity”

Authorization“a security mechanism used to determine user/client privileges or access levels

related to system resources”

Page 11: Instant ACLs with Zend Framework 2

11

Page 12: Instant ACLs with Zend Framework 2

In ZF2

WHO Zend/Authentication

Page 13: Instant ACLs with Zend Framework 2

In ZF2

WHO Zend/Authentication

Authenticate against:• DB table• LDAP• HTTP• And more…

Page 14: Instant ACLs with Zend Framework 2

In ZF2

WHAT Zend/Permissions/AclZend/Permissions/Rbac

Page 15: Instant ACLs with Zend Framework 2

In ZF2

WHAT Zend/Permissions/AclZend/Permissions/Rbac

Identity

Role Permission

Resource

Page 16: Instant ACLs with Zend Framework 2

SEEMS TOUGH…

Page 17: Instant ACLs with Zend Framework 2

JUST AS IT SHOULD!

Page 18: Instant ACLs with Zend Framework 2

CONSEQUENCES COULD BE UNDERESTIMATED

Page 19: Instant ACLs with Zend Framework 2

How does ZF2 help?

19

Page 20: Instant ACLs with Zend Framework 2
Page 21: Instant ACLs with Zend Framework 2

‘NUFF TALK. TIME FOR ACTION…

Page 22: Instant ACLs with Zend Framework 2

1ST NEEDWe need to add/editconferences through

a restricted area

Page 23: Instant ACLs with Zend Framework 2
Page 24: Instant ACLs with Zend Framework 2

THE ADMINISTRATOR

NEEDS TO BE RECOGNIZED

Page 25: Instant ACLs with Zend Framework 2

THE ADMINISTRATOR

NEEDS TO BE RECOGNIZEDNEEDS TO BE IDENTIFIED

Page 26: Instant ACLs with Zend Framework 2

HEAD TO OFFICIAL MODULES’ WEBSITE

Page 27: Instant ACLs with Zend Framework 2

OH, LOOK WHAT WE JUST GOT!

Page 28: Instant ACLs with Zend Framework 2

Installing and enabling ZfcUser

28

// composer.json

"require": {"zf-commons/zfc-user-doctrine-orm": "0.1.*"

}

Page 29: Instant ACLs with Zend Framework 2

Installing and enabling ZfcUser

29

// composer.json

"require": {"zf-commons/zfc-user-doctrine-orm": "0.1.*"

}

let’s suppose we use the Doctrine ORM

Page 30: Instant ACLs with Zend Framework 2

Installing and enabling ZfcUser

30

// composer.json

"require": {"zf-commons/zfc-user-doctrine-orm": "0.1.*"

}

// config/application.config.php

<?phpreturn array(

'modules' => array(// ...'ZfcBase','ZfcUser','ZfcUserDoctrineORM',

),);

Page 31: Instant ACLs with Zend Framework 2

Back to our user…

31

Page 32: Instant ACLs with Zend Framework 2

How shall we represent him?

Page 33: Instant ACLs with Zend Framework 2

class Systemuser {

private $id;

private $name;

private $city;

private $birthday;

private $username;

private $password;

}

We need a class

Page 34: Instant ACLs with Zend Framework 2

class Systemuser {

private $id;

private $name;

private $city;

private $birthday;

private $username;

private $password;

}

With some mandatory fields

Page 35: Instant ACLs with Zend Framework 2

class Systemuserimplements\ZfcUser\Entity\UserInterface {

private $id;

private $name;

private $city;

private $birthday;

private $username;

private $password;

}

Implementing an interface

Page 36: Instant ACLs with Zend Framework 2

Let’s configure ZfcUser

36

// config/autoload/zfcuser.global.php

/** ZfcUser Configuration */

$settings = array(

/** User Model Entity Class */'user_entity_class' => 'Application\Entity\Systemuser',

/** Start configuration for ZfcUserDoctrineORM */'enable_default_entities' => false,

);

Page 37: Instant ACLs with Zend Framework 2

Yay, here’s our working login form!

37

Page 38: Instant ACLs with Zend Framework 2

Yay, here’s our working login form!

38

Available at:http://myaddress/user/login

Page 39: Instant ACLs with Zend Framework 2

Yay, it works!

39

Page 40: Instant ACLs with Zend Framework 2

ZfcUser also allows to:• 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…

40

Page 41: Instant ACLs with Zend Framework 2

ZfcUser also allows to:• 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…

41

Page 42: Instant ACLs with Zend Framework 2

Remember the two steps?

WHO

WHAT

Page 43: Instant ACLs with Zend Framework 2

Remember the two steps?

WHO

WHAT

Page 44: Instant ACLs with Zend Framework 2

We need an admin panel!

44

Page 45: Instant ACLs with Zend Framework 2

We need an admin panel!

45

Welcome ZfcAdmin!provides a ready to use /admin route

Page 46: Instant ACLs with Zend Framework 2

hubme.in has an admin panel!

Page 47: Instant ACLs with Zend Framework 2

hubme.in has an admin panel!

Page 48: Instant ACLs with Zend Framework 2

Are we done yet?

48

Page 49: Instant ACLs with Zend Framework 2

What ifa malicious user…

Page 50: Instant ACLs with Zend Framework 2

What ifa malicious user…

Page 51: Instant ACLs with Zend Framework 2

What ifa malicious user…

…hits this url:http://myawesomewebsite/admin/conferences

Page 52: Instant ACLs with Zend Framework 2

What ifa malicious user…

…hits this url:http://myawesomewebsite/admin/conferences

accessible to everyone!

Page 53: Instant ACLs with Zend Framework 2

What ifa malicious user…

…hits this url:http://myawesomewebsite/admin/conferences

nothing’s protectingour private area

Page 54: Instant ACLs with Zend Framework 2

What ifa malicious user…

…hits this url:http://myawesomewebsite/admin/conferences

nothing’s protectingour private area

Login form could be bypassed!

Page 55: Instant ACLs with Zend Framework 2

No worries!

55

/** On each action*/

<?php

public function indexAction() {

if (!$this->zfcUserAuthentication()->hasIdentity()) {

return $this->redirect()->toRoute('home');

}

}

Page 56: Instant ACLs with Zend Framework 2

No worries!

56

/** On each action*/

<?php

public function indexAction() {

if (!$this->zfcUserAuthentication()->hasIdentity()) {

return $this->redirect()->toRoute('home');

}

} in EACH actionof EACH controller

Page 57: Instant ACLs with Zend Framework 2

WHAAAT?

Page 58: Instant ACLs with Zend Framework 2

IN EACH ACTION???

Page 59: Instant ACLs with Zend Framework 2

SOMEONE HELP US!

Page 60: Instant ACLs with Zend Framework 2

ZEND\PERMISSIONS\ACL

Page 61: Instant ACLs with Zend Framework 2

Remember? There were two steps…

WHO

WHAT

Page 62: Instant ACLs with Zend Framework 2

Using Zend/Permissions/Acl

62

<?php

use Zend\Permissions\Acl\Acl; use Zend\Permissions\Acl\Role\GenericRole as Role; use Zend\Permissions\Acl\Resource\GenericResource as Resource;

$acl = new Acl();

$acl->addRole(new Role('guest'))->addRole(new Role('admin'));

$acl->addResource(new Resource('someResource')); $acl->addResource(new Resource('adminarea')); $acl->addResource(new Resource('adminconferencearea')); $acl->addResource(new Resource('adminsettingsarea'));

$acl->allow('guest', 'someResource'); $acl->allow('admin', 'adminarea');$acl->allow('admin', 'adminconferencearea ');$acl->allow('admin', 'adminsettingsarea ');

Page 63: Instant ACLs with Zend Framework 2

Welcome BjyAuthorize!

63

… a facade for Zend\Permissions\Acl

that will ease its usage with modules

and applications …

From https://github.com/bjyoungblood/BjyAuthorize

Page 64: Instant ACLs with Zend Framework 2

Welcome BjyAuthorize!

64

… a facade for Zend\Permissions\Acl

that will ease its usage with modules

and applications …

From https://github.com/bjyoungblood/BjyAuthorize

Page 65: Instant ACLs with Zend Framework 2

OUR EASIER WAY

Page 66: Instant ACLs with Zend Framework 2

How does it work?

66

Page 67: Instant ACLs with Zend Framework 2

Standard Zend\Mvc app workflow

67

From https://github.com/bjyoungblood/BjyAuthorize

Page 68: Instant ACLs with Zend Framework 2

With BjyAuthorize enabled

68

From https://github.com/bjyoungblood/BjyAuthorize

Page 69: Instant ACLs with Zend Framework 2

With BjyAuthorize enabled

69

From https://github.com/bjyoungblood/BjyAuthorize

Page 70: Instant ACLs with Zend Framework 2

With BjyAuthorize enabled

70

From https://github.com/bjyoungblood/BjyAuthorize

Page 71: Instant ACLs with Zend Framework 2

With BjyAuthorize enabled

71

From https://github.com/bjyoungblood/BjyAuthorize

+ control over resources

Page 72: Instant ACLs with Zend Framework 2

Installing and enabling BjyAuthorize

72

// composer.json

"require": {"bjyoungblood/bjy-authorize": "1.4.*"

}

// config/application.config.php

<?phpreturn array(

'modules' => array(// ...'BjyAuthorize',

),);

Page 73: Instant ACLs with Zend Framework 2

Configuring BjyAuthorize

73

// config/autoload/bjyauthorize.global

return array(

'bjyauthorize' => array(

'default_role' => 'guest',

'identity_provider' =>'BjyAuthorize\Provider\Identity\AuthenticationIdentityProvider',

'role_providers' => array('BjyAuthorize\Provider\Role\Config' => array( 'guest' => array(), 'admin' => array(), ),

),

), );

Page 74: Instant ACLs with Zend Framework 2

Configuring BjyAuthorize

74

// config/autoload/bjyauthorize.global

return array(

'bjyauthorize' => array(

'default_role' => 'guest',

'identity_provider' =>'BjyAuthorize\Provider\Identity\AuthenticationIdentityProvider',

'role_providers' => array('BjyAuthorize\Provider\Role\Config' => array( 'guest' => array(), 'admin' => array(), ),

),

), );

A new concept: the Role

Page 75: Instant ACLs with Zend Framework 2

Guards on routes

75

Allowed to all users

http://myawesomewebsite/

Page 76: Instant ACLs with Zend Framework 2

Guards on routeshttp://myawesomewebsite/

76

Allowed to all users

http://myawesomewebsite/admin/...

Restricted area! For admins only

Page 77: Instant ACLs with Zend Framework 2

Guards on controller actions

77

class ConferencesController {

public function listAction() {

// code...

}

public function manageAction() {

// code...

}

}

Page 78: Instant ACLs with Zend Framework 2

Guards on controller actions

78

Allowed to all users

class ConferencesController {

public function listAction() {

// code...

}

public function manageAction() {

// code...

}

}

Page 79: Instant ACLs with Zend Framework 2

Guards on controller actions

79

Allowed to all users

class ConferencesController {

public function listAction() {

// code...

}

public function manageAction() {

// code...

}

}Restricted area! For admins only

Page 80: Instant ACLs with Zend Framework 2

Guards on controller actions

80

array(

'controller' => 'ZfcAdmin\Controller\AdminController','roles' => array('admin')

)

Page 81: Instant ACLs with Zend Framework 2

81

Where shouldguards be placed?

Page 82: Instant ACLs with Zend Framework 2

Inside each module configuration

82

// module/Conferences/config/module.config.php

return array(

'bjyauthorize' => array(

'guards' => array(

'BjyAuthorize\Guard\Controller' => array(

//...

),

), ),

Page 83: Instant ACLs with Zend Framework 2

Inside each module configuration

83

// module/Conferences/config/module.config.php

return array(

'bjyauthorize' => array(

'guards' => array(

'BjyAuthorize\Guard\Controller' => array(

//...

),

), ),

Taking advantage of ZF2 configuration merge

Page 84: Instant ACLs with Zend Framework 2

It works!

Page 85: Instant ACLs with Zend Framework 2

It works!

User could be redirectedto whatever url we want

Page 86: Instant ACLs with Zend Framework 2

Dude, forgot to tellya! …we got 2

fellas!

2ND NEED

Page 87: Instant ACLs with Zend Framework 2

Two different roles

87

The reader

Page 88: Instant ACLs with Zend Framework 2

Two different roles

88

The reader

Page 89: Instant ACLs with Zend Framework 2

Two different roles

89

The reader The editor

Page 90: Instant ACLs with Zend Framework 2

Two different roles

90

The reader The editor

Can only viewconference info

Can viewconferences +

create, edit and delete info

Page 91: Instant ACLs with Zend Framework 2

What we want

Only editor shouldsee these icons

Page 92: Instant ACLs with Zend Framework 2
Page 93: Instant ACLs with Zend Framework 2

Until now…

93

'bjyauthorize' => array(

// ...

'role_providers' => array('BjyAuthorize\Provider\Role\Config' => array( 'guest' => array(), 'admin' => array(),

), ),

)

Static role list

Page 94: Instant ACLs with Zend Framework 2

94

'bjyauthorize' => array(

// ...

'role_providers' => array('BjyAuthorize\Provider\Role\Config' => array( 'guest' => array(), 'admin' => array(),

), ),

)

More flexibility wouldn’t hurt…

Until now…

Page 95: Instant ACLs with Zend Framework 2

BjyAuthorize config changes

95

// config/autoload/bjyauthorize.global

return array(

'bjyauthorize' => array(

'role_providers' => array(

'BjyAuthorize\Provider\Role\ObjectRepositoryProvider' => array(

'role_entity_class' => 'Application\Entity\Role','object_manager' => 'doctrine.entity_manager.orm_default', ),

),

), );

From array to class (persisted on db)

Page 96: Instant ACLs with Zend Framework 2

Let’s map the actions

Page 97: Instant ACLs with Zend Framework 2

New concept: the Resource

Page 98: Instant ACLs with Zend Framework 2

something

Page 99: Instant ACLs with Zend Framework 2

somethingupon which

someone

Page 100: Instant ACLs with Zend Framework 2

somethingupon which

someonecould perform

an action

Page 101: Instant ACLs with Zend Framework 2

ENTITY

IDENTITY / ROLE

PRIVILEGE

Page 102: Instant ACLs with Zend Framework 2

On BjyAuthorize…

102

'resource_providers' => array('BjyAuthorize\Provider\Resource\Config' => array( 'Conference' => array(),

), ),

'rule_providers' => array('BjyAuthorize\Provider\Rule\Config' => array( 'allow' => array(

// allow editors to edit conferencesarray(array('editor'), 'Conference', array('edit')),

), ),

Page 103: Instant ACLs with Zend Framework 2

On views…

103

//Conferences/view/…/index.phtml

<?php if ($this->isAllowed($event, 'edit')) { ?>

<a href="someurl">Remove</a><br /><a href="someurl">Edit</a>

<?php } ?>

Page 104: Instant ACLs with Zend Framework 2

Views, routes and controllers are safe

104

Page 105: Instant ACLs with Zend Framework 2

Views, routes and controllers are safe

Is this enough?

105

Page 106: Instant ACLs with Zend Framework 2

Another controller, another action

106

//Conferences/Controller/AnotherAdminController.php

class AnotherAdminController extends AbstractActionController {

public function someCrazyAction() {

//...

$this->conferenceService->updateConference($myConference);

}

}

What prevents this?

Page 107: Instant ACLs with Zend Framework 2

Choose your protection level

107

ROUT

E

CONT

ROLL

ER

SERV

ICE

Page 108: Instant ACLs with Zend Framework 2

Conference service

108

//Conferences/Service/ConferenceService.php

namespace Conferences\Service;

class ConferenceService {

public function getConference($id) { ... }

public function getConferenceList($someCriteria) { ... }

public function updateConference($myConf) { ... }

public function deleteConference($myConf) { ... }

}

Page 109: Instant ACLs with Zend Framework 2

Conference service

109

//Conferences/Service/ConferenceService.php

namespace Conferences\Service;

class ConferenceService {

public function getConference($id) { ... }

public function getConferenceList($someCriteria) { ... }

public function updateConference($myConf) { ... }

public function deleteConference($myConf) { ... }

}

Only to allowed users!

Page 110: Instant ACLs with Zend Framework 2

Let’s inject the Authorize class

110

//Conferences/Service/ConferenceServiceFactory.php

namespace Conferences\Service;

class ConferenceServiceFactory implements FactoryInterface {

public function createService(ServiceLocatorInterface $serviceLocator){

//...

$authorize = $serviceLocator->get('BjyAuthorize\Service\Authorize');

return new ConferenceService(..., $authorize);

}

}

Page 111: Instant ACLs with Zend Framework 2

Updated conference service

111

//Conferences/Service/ConferenceService.php

namespace Conferences\Service;

class ConferenceService {

//...

public function updateConference($myConf) {

if (!$this->authorize->isAllowed($myConf, 'edit')) {

throw new UnAuthorizedException();

}

// other code...

} // the same for deleteConference method }

Page 112: Instant ACLs with Zend Framework 2

Now our service is secured

112

ROUT

E

CONT

ROLL

ER

SERV

ICE

Page 113: Instant ACLs with Zend Framework 2

3RD NEEDWe’ll outsource the management of

foreign conferences

Page 114: Instant ACLs with Zend Framework 2
Page 115: Instant ACLs with Zend Framework 2

Based on their country

Page 116: Instant ACLs with Zend Framework 2

How database changes

116

class Systemuser {

//...

private $country;

}

class Conference {

//...

private $country;

}

Page 117: Instant ACLs with Zend Framework 2

Create an Assertion

117

use Zend\Permissions\Acl\Assertion\AssertionInterface;

class CheckUserCountry implements AssertionInterface {

// ...

public function assert(Acl $acl, RoleInterface $role = null,ResourceInterface $resource = null,$privilege = null) {

// ...

}

}

Page 118: Instant ACLs with Zend Framework 2

Create an Assertion

118

use Zend\Permissions\Acl\Assertion\AssertionInterface;

class CheckUserCountry implements AssertionInterface {

// ...

public function assert(Acl $acl, RoleInterface $role = null,ResourceInterface $resource = null,$privilege = null) {

return $resource->getCountry() ==$this->loggedUser->getCountry();

}

}

Page 119: Instant ACLs with Zend Framework 2

Create an Assertion

119

use Zend\Permissions\Acl\Assertion\AssertionInterface;

class CheckUserCountry implements AssertionInterface {

// ...

public function assert(Acl $acl, RoleInterface $role = null,ResourceInterface $resource = null,$privilege = null) {

return $resource->getCountry() == $this->loggedUser->getCountry();

}

}

Injected through constructor

Page 120: Instant ACLs with Zend Framework 2

Create an Assertion

120

use Zend\Permissions\Acl\Assertion\AssertionInterface;

class CheckUserCountry implements AssertionInterface {

// ...

public function assert(Acl $acl, RoleInterface $role = null,ResourceInterface $resource = null,$privilege = null) {

return $resource->getCountry() ==$this->loggedUser->getCountry();

}

}

1 LoC… AWESOME!!

Page 121: Instant ACLs with Zend Framework 2

Update rule with the new assertion

121

'rule_providers' => array('BjyAuthorize\Provider\Rule\Config' => array( 'allow' => array(

// role check through assertionarray(array('editor'),

'Conference', array('edit'),'assertion.CheckUserCountry'),

), ),

Page 122: Instant ACLs with Zend Framework 2

122

The reader

Page 123: Instant ACLs with Zend Framework 2

123

The reader

The editor

Page 124: Instant ACLs with Zend Framework 2

In the same way we could:• Restrict access to user owned

onferences only• or conferences owned by a group the

user is belonging to• …and much more!

124

Page 125: Instant ACLs with Zend Framework 2

4TH NEEDCool. How'bout the admin menu

though?

Page 126: Instant ACLs with Zend Framework 2

Navigation menu

126

Page 127: Instant ACLs with Zend Framework 2

Configure Zend/Navigation

127

// module/Conferences/config/module.config.php

return array(

'navigation' => array('admin' => array(

'conferences' => array('label' => 'Conferences','route' => 'zfcadmin/conferences','resource' => 'Conference','privilege' => 'view',

),),

),

), );

Page 128: Instant ACLs with Zend Framework 2

Configure Zend/Navigation

128

// module/Settings/config/module.config.php

return array(

'navigation' => array('admin' => array(

'settings' => array('label' => 'Settings','route' => 'zfcadmin/settings','resource' => 'Setting','privilege' => 'view',

),),

),

), );

Page 129: Instant ACLs with Zend Framework 2

How menu looks like for admins

Page 130: Instant ACLs with Zend Framework 2

How menu looks like for other users

Page 131: Instant ACLs with Zend Framework 2

FINAL NOTES

Page 132: Instant ACLs with Zend Framework 2

PLUGGABLE COMPONENTS

Page 133: Instant ACLs with Zend Framework 2

PLUGGABLE COMPONENTS

CLEAN ARCHITECTURE

Page 134: Instant ACLs with Zend Framework 2

PLUGGABLE COMPONENTS

CLEAN ARCHITECTURE

COMPLEX ACL LOGIC IN A FEW MINUTES

Page 135: Instant ACLs with Zend Framework 2

Stefano [email protected]@mvassociati.it

Thank you for your attention!

Page 136: Instant ACLs with Zend Framework 2

Stefano [email protected]@mvassociati.it

Questions?

Page 137: Instant ACLs with Zend Framework 2

Photo CreditsFrom Flickr:http://www.flickr.com/photos/cbpphotos/8652042987http://www.flickr.com/photos/disa4ever/9409743179http://www.flickr.com/photos/ben_salter/6169305845http://www.flickr.com/photos/elzey/3481161467http://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.asphttp://www.fanpop.com/clubs/the-a-team/imageshttp://dwightschultz.freeforums.org/dwight-photo-s-t8.htmlhttp://docmanhattan.blogspot.it/2010/10/vita-mort-immortalita-e-miracoli-di-mr.htmlhttp://www.starsky-iom.com/forum/viewtopic.php?f=8&t=58http://www.thea-teamonline.com/

And others form iStockPhoto

137