Instant ACLs with Zend Framework 2

Post on 05-Dec-2014

9.768 views 3 download

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

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

Instant ACLswith Zend Framework 2

@stefanovalle

http://www.mvlabs.it/

http://friuli.grusp.org/

5

AUTHENTICATION AUTHORIZATION

Two step process

Two step process

WHO

WHAT

Two step process

WHO

WHAT

Authentication

Definitions from http://www.techopedia.com

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

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”

11

In ZF2

WHO Zend/Authentication

In ZF2

WHO Zend/Authentication

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

In ZF2

WHAT Zend/Permissions/AclZend/Permissions/Rbac

In ZF2

WHAT Zend/Permissions/AclZend/Permissions/Rbac

Identity

Role Permission

Resource

SEEMS TOUGH…

JUST AS IT SHOULD!

CONSEQUENCES COULD BE UNDERESTIMATED

How does ZF2 help?

19

‘NUFF TALK. TIME FOR ACTION…

1ST NEEDWe need to add/editconferences through

a restricted area

THE ADMINISTRATOR

NEEDS TO BE RECOGNIZED

THE ADMINISTRATOR

NEEDS TO BE RECOGNIZEDNEEDS TO BE IDENTIFIED

HEAD TO OFFICIAL MODULES’ WEBSITE

OH, LOOK WHAT WE JUST GOT!

Installing and enabling ZfcUser

28

// composer.json

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

}

Installing and enabling ZfcUser

29

// composer.json

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

}

let’s suppose we use the Doctrine ORM

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',

),);

Back to our user…

31

How shall we represent him?

class Systemuser {

private $id;

private $name;

private $city;

private $birthday;

private $username;

private $password;

}

We need a class

class Systemuser {

private $id;

private $name;

private $city;

private $birthday;

private $username;

private $password;

}

With some mandatory fields

class Systemuserimplements\ZfcUser\Entity\UserInterface {

private $id;

private $name;

private $city;

private $birthday;

private $username;

private $password;

}

Implementing an interface

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,

);

Yay, here’s our working login form!

37

Yay, here’s our working login form!

38

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

Yay, it works!

39

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

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

Remember the two steps?

WHO

WHAT

Remember the two steps?

WHO

WHAT

We need an admin panel!

44

We need an admin panel!

45

Welcome ZfcAdmin!provides a ready to use /admin route

hubme.in has an admin panel!

hubme.in has an admin panel!

Are we done yet?

48

What ifa malicious user…

What ifa malicious user…

What ifa malicious user…

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

What ifa malicious user…

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

accessible to everyone!

What ifa malicious user…

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

nothing’s protectingour private area

What ifa malicious user…

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

nothing’s protectingour private area

Login form could be bypassed!

No worries!

55

/** On each action*/

<?php

public function indexAction() {

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

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

}

}

No worries!

56

/** On each action*/

<?php

public function indexAction() {

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

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

}

} in EACH actionof EACH controller

WHAAAT?

IN EACH ACTION???

SOMEONE HELP US!

ZEND\PERMISSIONS\ACL

Remember? There were two steps…

WHO

WHAT

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 ');

Welcome BjyAuthorize!

63

… a facade for Zend\Permissions\Acl

that will ease its usage with modules

and applications …

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

Welcome BjyAuthorize!

64

… a facade for Zend\Permissions\Acl

that will ease its usage with modules

and applications …

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

OUR EASIER WAY

How does it work?

66

Standard Zend\Mvc app workflow

67

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

With BjyAuthorize enabled

68

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

With BjyAuthorize enabled

69

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

With BjyAuthorize enabled

70

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

With BjyAuthorize enabled

71

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

+ control over resources

Installing and enabling BjyAuthorize

72

// composer.json

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

}

// config/application.config.php

<?phpreturn array(

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

),);

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(), ),

),

), );

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

Guards on routes

75

Allowed to all users

http://myawesomewebsite/

Guards on routeshttp://myawesomewebsite/

76

Allowed to all users

http://myawesomewebsite/admin/...

Restricted area! For admins only

Guards on controller actions

77

class ConferencesController {

public function listAction() {

// code...

}

public function manageAction() {

// code...

}

}

Guards on controller actions

78

Allowed to all users

class ConferencesController {

public function listAction() {

// code...

}

public function manageAction() {

// code...

}

}

Guards on controller actions

79

Allowed to all users

class ConferencesController {

public function listAction() {

// code...

}

public function manageAction() {

// code...

}

}Restricted area! For admins only

Guards on controller actions

80

array(

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

)

81

Where shouldguards be placed?

Inside each module configuration

82

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

return array(

'bjyauthorize' => array(

'guards' => array(

'BjyAuthorize\Guard\Controller' => array(

//...

),

), ),

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

It works!

It works!

User could be redirectedto whatever url we want

Dude, forgot to tellya! …we got 2

fellas!

2ND NEED

Two different roles

87

The reader

Two different roles

88

The reader

Two different roles

89

The reader The editor

Two different roles

90

The reader The editor

Can only viewconference info

Can viewconferences +

create, edit and delete info

What we want

Only editor shouldsee these icons

Until now…

93

'bjyauthorize' => array(

// ...

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

), ),

)

Static role list

94

'bjyauthorize' => array(

// ...

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

), ),

)

More flexibility wouldn’t hurt…

Until now…

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)

Let’s map the actions

New concept: the Resource

something

somethingupon which

someone

somethingupon which

someonecould perform

an action

ENTITY

IDENTITY / ROLE

PRIVILEGE

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')),

), ),

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 } ?>

Views, routes and controllers are safe

104

Views, routes and controllers are safe

Is this enough?

105

Another controller, another action

106

//Conferences/Controller/AnotherAdminController.php

class AnotherAdminController extends AbstractActionController {

public function someCrazyAction() {

//...

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

}

}

What prevents this?

Choose your protection level

107

ROUT

E

CONT

ROLL

ER

SERV

ICE

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) { ... }

}

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!

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);

}

}

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 }

Now our service is secured

112

ROUT

E

CONT

ROLL

ER

SERV

ICE

3RD NEEDWe’ll outsource the management of

foreign conferences

Based on their country

How database changes

116

class Systemuser {

//...

private $country;

}

class Conference {

//...

private $country;

}

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) {

// ...

}

}

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();

}

}

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

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!!

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'),

), ),

122

The reader

123

The reader

The editor

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

4TH NEEDCool. How'bout the admin menu

though?

Navigation menu

126

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',

),),

),

), );

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',

),),

),

), );

How menu looks like for admins

How menu looks like for other users

FINAL NOTES

PLUGGABLE COMPONENTS

PLUGGABLE COMPONENTS

CLEAN ARCHITECTURE

PLUGGABLE COMPONENTS

CLEAN ARCHITECTURE

COMPLEX ACL LOGIC IN A FEW MINUTES

Stefano Valle@stefanovalles.valle@mvassociati.it

Thank you for your attention!

Stefano Valle@stefanovalles.valle@mvassociati.it

Questions?

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