| Ratings |  | Unique User Downloads |  | Download Rankings | 
| Not yet rated by the users |  | Total: 232 |  | All time:  8,136 This week: 53  | 
|  | 
| Description |  | Author | 
| This package can HTTP authentication using PSR-7 interfaces.
 It uses PSR-7 interface implementation for request and response classes that will read the authentication request values and generates the necessary responses.
 
 Separate classes implement the authentication of users from a file based database of user and password records.
 
 It provides classes to check if the user is already logged in an authenticate him in case he isn't.
Innovation Award 
|  August 2017
 Number 13
 | PSR-7 is a PHP standards recommendation for abstracting information sent and received via HTTP requests. 
 This package implements a user authentication system that abstracts the way HTTP request and response headers are sent and received, so it can work with many different Web server architectures.
 
 Manuel Lemos
 |  |  | 
|  |  | Innovation award 
  Nominee: 2x
 | 
 
 | 
Example
| 
<?phpnamespace Poirot\AuthSystem\Authenticate\Identifier\HttpDigest
 {
 use Poirot\Http\Interfaces\iHttpRequest;
 
 /**
 * Has Request Contains Authorization Header
 *
 * @param iHttpRequest $request
 * @param bool         $isProxy
 *
 * @return bool
 */
 function hasAuthorizationHeader(iHttpRequest $request, $isProxy = false)
 {
 if ($isProxy)
 $headerName = 'Proxy-Authorization';
 else
 $headerName = 'Authorization';
 
 
 $hValue = false;
 
 $headers = $request->headers();
 if ($headers->has($headerName)) {
 $h = $headers->get($headerName)->current();
 $hValue = $h->renderValueLine();
 }
 
 return $hValue;
 }
 
 /**
 * Parse Authorization Header
 *
 * Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
 *
 * - in case of basic extract given username/password
 *
 * @param string      $headerValue
 * @param null|string $clientScheme Basic|Digest, null detect from header
 *
 * @return array
 * @throws \Exception
 */
 function parseAuthorizationHeader($headerValue, $clientScheme = null)
 {
 if ($clientScheme === null) {
 list($clientScheme) = explode(' ', trim($headerValue));
 $clientScheme       = strtolower($clientScheme);
 }
 
 if (!in_array($clientScheme, array('basic', 'digest')))
 throw new \Exception(sprintf('Client Scheme (%s) Not Supported.', $clientScheme));
 
 if ($clientScheme == 'basic')
 $parsed = parseBasicAuthorizationHeader($headerValue);
 else
 $parsed = parseDigestAuthorizationHeader($headerValue);
 
 return $parsed;
 }
 
 /**
 * Parse Basic Authorization Header Value To It's
 * Credential Values
 *
 * Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
 *
 * @param string $headerValue
 *
 * @return array [username=>'', 'password'=>'']
 * @throws \Exception Invalid Header
 */
 function parseBasicAuthorizationHeader($headerValue)
 {
 // Decode the Authorization header
 $auth = substr($headerValue, strlen('Basic '));
 $auth = base64_decode($auth);
 if (!$auth)
 throw new \RuntimeException('Unable to base64_decode Authorization header value');
 
 if (!ctype_print($auth))
 throw new \Exception('Invalid or Empty Authorization Credential.');
 
 $creds = array_filter(explode(':', $auth));
 if (count($creds) != 2)
 throw new \Exception('Invalid Authorization Credential; Missing username or password.');
 
 $credential = array('username' => $creds[0], 'password' => $creds[1], 0=>$creds[0], 1=>$creds[1]);
 return $credential;
 }
 
 /**
 * Parse Digest Authorization header
 *
 * credentials = "Digest" digest-response
 * digest-response = 1#( username | realm | nonce | digest-uri
 *      | response | [ algorithm ] | [cnonce] | [opaque]
 *      | [message-qop] | [nonce-count] | [auth-param] )
 *
 * @param string $headerValue
 *
 * @return array
 * @throws \Exception Invalid Header
 */
 function parseDigestAuthorizationHeader($headerValue)
 {
 preg_match_all('@(\w+)=(?:(?:")([^"]+)"|([^\s,$]+))@', $headerValue, $matches, PREG_SET_ORDER);
 
 $data = array();
 foreach ($matches as $m) {
 $key   = $m[1];
 $value = ($m[2]) ? $m[2] : $m[3];
 
 switch ($key) {
 case 'realm':
 case 'username':
 if (!ctype_print($value))
 throw new \Exception('Invalid "realm" or "username"');
 break;
 case 'nonce':
 if (!ctype_xdigit($value))
 throw new \Exception('Invalid "nonce"');
 break;
 /*
 * A string of 32 hex digits computed as defined below, which proves
 * that the user knows a password
 */
 case 'response':
 if (32 != strlen($value) || !ctype_xdigit($value))
 throw new \Exception('Invalid "response"');
 break;
 /*
 * Indicates what "quality of protection" the client has applied to
 * the message. If present, its value MUST be one of the alternatives
 * the server indicated it supports in the WWW-Authenticate header.
 */
 case 'qop':
 break;
 /*
 * This MUST be specified if a qop directive is sent (see above), and
 * MUST NOT be specified if the server did not send a qop directive in
 * the WWW-Authenticate header field. The nc-value is the hexadecimal
 * count of the number of requests (including the current request)
 * that the client has sent with the nonce value in this request. For
 * example, in the first request sent in response to a given nonce
 * value, the client sends "nc=00000001". The purpose of this
 * directive is to allow the server to detect request replays by
 * maintaining its own copy of this count - if the same nc-value is
 * seen twice, then the request is a replay.
 */
 case 'nc':
 if (8 != strlen($value) || !ctype_xdigit($value))
 throw new \Exception('Invalid "nc"');
 break;
 }
 
 $data[$key] = $value;
 }
 
 return $data;
 
 ## cnonce -----------------------------------------------------------------
 /*
 * Nonce-count. This a hexadecimal serial number for the request.
 * The client should increase this number by one for every request.
 *
 * This MUST be specified if a qop directive is sent (see above), and
 * MUST NOT be specified if the server did not send a qop directive in
 * the WWW-Authenticate header field. The cnonce-value is an opaque
 * quoted string value provided by the client and used by both client
 * and server to avoid chosen plaintext attacks, to provide mutual
 * authentication, and to provide some message integrity protection.
 */
 }
 }
 
 | 
Details
Poirot\AuthSystem
HTTP authentication using PSR-7 interfaces.
It uses PSR-7 interface implementation for request and response classes that will read the authentication request values and generates the necessary responses.
Separate classes implement the authentication of users from a file based database of user and password records.
It provides classes to check if the user is already logged in an authenticate him in case he isn't.
Overview usage sample
$request  = new HttpRequest(new PhpServerRequestBuilder);
$response = new HttpResponse(new PhpServerResponseBuilder);
$lazyLoad = new LazyFulfillmentIdentity(['fulfillment_by' => 'username', 'data_provider' => new UserData]);
$auth     = new Authenticator\HttpSessionAuth([
    'identity' => $lazyLoad,
    'request'  => $request,
    'response' => $response,
]);
try {
    $credential = null;
    ## check user has authenticated
    login_user:
    $auth->authenticate($credential);
    echo 'Continue ...';
    if (!$auth->isSignIn()) {
        $auth->signIn();
        header('Location: '.$request->getUri()->getPath()->toString());
        die();
    }
} catch (WrongCredentialException $e) {
    throw new \Exception('Invalid Username or Password.');
} catch (UserNotFoundException $e) {
    throw new \Exception('Invalid Username or Password.');
} catch (AuthenticationException $e)
{
    if ($e->getAuthenticator() instanceof Authenticator\HttpSessionAuth)
    {
        ### handle login with satisfy request
        if ($request->plg()->methodType()->isPost()) {
            $credential = new UserPassCredential($request->plg()->phpServer()->getPost());
            goto login_user;
        }
        ### challenge user with login form, redirection or etc.
        $response->setBody('
                <form method="post" action="" enctype="application/x-www-form-urlencoded">
                     <input type="text" name="email">
                     <input type="password" name="password">
                     <input type="submit" value="send">
                </form>
                <p>Please Login ...</p>
            ');
    }
}
## run rest of program
if ($auth->hasAuthenticated()) {
    $response->setBody("<h1>Hello User {$auth->identity()->getEmail()}</h1>");
}
### send response
$response->flush();
TODO
- 
Aggregate Authenticator
- 
Aggregate Adapter
- 
Write Authentication Service Layer On Top Of Adapters For Application Dispatching Control 
|  | Applications that use this package |  | 
No pages of applications that use this class were specified.
 If you know an application of this package, send a message to the author to add a link here.
 If you know an application of this package, send a message to the author to add a link here.