donate Buy us a cup of coffee
Our service is free. But your donation can help us keep running. To rent a server and domain, to buy us a cup of coffee, to reduce our activity in paid stuff and make this service better. You can send us a donation to BCA Bank, 008 090 8440 in the name of Abdul Malik Ikhsan with Swifcode CENAIDJA. Please confirm to samsonasik@gmail.com after that ;).
download Download module      



Authentication example with Zend Framework 2

After each successful authentication, please restart your browser. Each authentication last for an hour.

The Zend\Authentication\Adapter\Http provides an easy way for Apache like authentication in Zend Framework 2 applications.

It comes with two implementations Basic and Digest HTTP Authentication, which can be combined with two sub components - the class itself or a FileResolver. We are going to use the FileResolver to read the stored credentials and compare them to the submitted values.

First thing first. There are few important things to know.

1. Create a folder with name auth in MODULE_NAME/config/. Inside that folder create two files basic.txt and digest.txt. The file formats are smillar to Apache .htpasswd files.
Basic - <username>:<realm>:<credentials>, here credentials should be written in clear text, e.g.: basic:authentication:plaintextpassword.
Digest - <username>:<realm>:<credentials>, where <credentials> is the md5 hash of all 3 parts, e.g.: digest:authentication:dc45122ef294d83e84a8b5a3a6c5356b

2. In the same module, where we have just created our auth folder, open module.config.php file and place this code.


    /**
     * Used for basic authentication
     */
    'authentication_basic' => [
        'adapter' => [
            'config' => [
                'accept_schemes' => 'basic',
                'realm'          => 'authentication',
                'nonce_timeout'  => 3600,
            ],
            'basic'  => __DIR__.'/auth/basic.txt',
        ],
    ],
    /**
     * Used for digest authentication
     */
    'authentication_digest' => [
        'adapter' => [
            'config' => [
                'accept_schemes' => 'digest',
                'realm'          => 'authentication',
                'digest_domains' => '/learn-zf2-authentication/digest',
                'nonce_timeout'  => 3600,
            ],
            'digest' => __DIR__.'/auth/digest.txt',
        ],
    ]

The code tells us which authentication schemes we accept, the realm (must be the same as the realm in the basic/digest.txt files, digest_domains (only when we use digest authentication) is the URL(s) where we want to apply the same valid information, nonce_timeout sets the number of seconds for which the nonce is valid.


LearnZF2Authentication\Factory\BasicAuthenticationAdapterFactory

    
        $config = $serviceLocator->get('Config');
        $authConfig = $config['authentication_basic']['adapter'];
        $authAdapter = new HttpAdapter($authConfig['config']);

        $basic = new FileResolver();
        $basic->setFile($authConfig['basic']);

        $authAdapter->setBasicResolver($basic);

        return $authAdapter;
        

LearnZF2Authentication\Factory\DigestAuthenticationAdapterFactory

    
        $config = $serviceLocator->get('Config');
        $authConfig = $config['authentication_digest']['adapter'];
        $authAdapter = new HttpAdapter($authConfig['config']);

        $digest = new FileResolver();
        $digest->setFile($authConfig['digest']);

        $authAdapter->setDigestResolver($digest);

        return $authAdapter;
        

These are the codes we use to pass the authentication information


Module.php

    
/**
 * @var MvcEvent $e
 */
$request  = $e->getRequest();
$response = $e->getResponse();
$view = $e->getApplication()->getMvcEvent()->getViewModel();
$sm = $e->getApplication()->getServiceManager();
$authAdapter = $sm->get('LearnZF2Authentication\BasicAuthenticationAdapter');

/**
 * Not HTTP? Stop!
 */
if (!($request instanceof Http\Request && $response instanceof Http\Response)) {
    return;
}

/**
 * Call the factory class and try to authenticate
 */
if ($e->getRouteMatch()->getParam('action') == 'digest') {
    $authAdapter = $sm->get('LearnZF2Authentication\DigestAuthenticationAdapter');
}
$authAdapter->setRequest($request);
$authAdapter->setResponse($response);

if($e->getRouteMatch()->getParam('action') == 'basic' || $e->getRouteMatch()->getParam('action') == 'digest') {
    $result = $authAdapter->authenticate();

    /**
     * Pass the information to the view and see what we got
     */
    if ($result->isValid()) {
        return $view->identity = $result->getIdentity();
    } else {
        /**
         * Create a log function or just use the one from LearnZF2.
         * Also make sure to redirect to another page, 404 for example
         */
        foreach ($result->getMessages() as $msg) {
            return $view->authProblem = $msg;
        }
    }
}
        

This is the code we use to pass the authentication information


One last important thing to note is that you must include a special header called Authorization n your request, replace :


            
        RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L]
            
with

        
# PHP compiled as CGI does not support apache_response_headers function, but we need this header in order to do basic HTTP authtentication when running with CGI or FastCGI.
RewriteRule ^(.*)$ %{ENV:BASE}index.php [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L,NC]
            
and add in top of public/index.php

    if (isset($_SERVER["REDIRECT_HTTP_AUTHORIZATION"])) {
       $_SERVER["HTTP_AUTHORIZATION"] = $_SERVER["REDIRECT_HTTP_AUTHORIZATION"];
   }


Some things to note. The auth folder as well the authentication code from module.config.php is best to be placed in your main config folder, where the global|local.php files are and excluded from commits.