Giter VIP home page Giter VIP logo

zend-expressive-authentication's Introduction

Expressive Authentication Middleware

Repository abandoned 2019-12-31

This repository has moved to mezzio/mezzio-authentication.

Build Status Coverage Status

zend-expressive-authentication provides middleware for Expressive and PSR-7 applications for the purpose of authenticating HTTP requests using consumer- or third-party-provided adapters.

Installation

You can install the zend-expressive-authentication library with composer:

$ composer require zendframework/zend-expressive-authentication

Documentation

Browse the documentation online at https://docs.zendframework.com/zend-expressive-authentication/.

zend-expressive-authentication's People

Contributors

ezimuel avatar froschdesign avatar geerteltink avatar internalsystemerror avatar jonsa avatar michalbundyra avatar nuxwin avatar olavocneto avatar samsonasik avatar steffenbrand avatar weierophinney avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zend-expressive-authentication's Issues

AuthenticationMiddleware does not work correctly when last in pipe chain. Cannot distinguish successful vs failed auth attempt.

A typical usage for authentication process is having AuthenticationMiddleware at the end of a login route/pipeline:

$app->route('/login', [
  \App\Handler\LoginHandler::class,
  \Zend\Expressive\Authentication\AuthenticationMiddleware::class
]);

where LoginHandler performs authentication process by

$this->loginForm->setData($request->getParsedBody());
if ($this->loginForm->isValid()) {
   $response = $handler->handle($request);
      if ($response->getStatusCode() !== 302) {
         return new RedirectResponse('/');
      }

   $error = 'Login Failure, please try again';
} 
// return html response with login form

Because it is last, return $handler->handle() in AuthenticationMiddleware always returns 404, causing the entire error handling template to be rendered and immediately discarded. I discovered this when for longest I couldn't tell why some code in my 404 template kept on crashing at least expected times... And of course unnecessary performance problem.

Expected results

  • Authentication adapter not cause unexpected error handling stack to execute, not assume there will always be another handler after it.
  • If there is another handler (eg. to control myself the redirect process), may need to know why 302 was caused. Perhaps AuthenticationResult needs to be returned instead of letting PhpSession run out of control?

Actual results

  • error templates rendered unexpectedly
  • Unable to differentiate whether 302 was caused by successful login, failed authorization, or log-out process to get around.

PDODatabase repository error: Trying to get property of non-object on wrong username

Provide a narrative description of what you are trying to accomplish.

When wrong username (username not found in DB) filled is wrong ( no username filled in db ), it got error:

Trying to get property of non-object

screen shot 2018-01-12 at 10 04 41 am

Code to reproduce the issue

I checked the code at UserRepository\PdoDatabase::authenticate(), the :

$result = $stmt->fetchObject();

is hit when we pass wrong username( no username record found ), then it return false, then, it can't be checked with $result->{$this->config['field']['password']};

Expected results

Working

Actual results

Got error :

Trying to get property of non-object

Make UserInterface::getIdentity() return an array

I've been having issues with the UserInterface. For the current application I'd like to have the ID, email address and name available. However for some other applications I only want a username. So in other words, the userinterface is pretty limited.

If we change the getIdentity method to an array or maybe add an extra getSessionAttributes() method to return an array with extra attributes, it would make it a lot more flexible.

public function getSessionAttributes() : array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'username' => $this->username,
    ];
}

Proposal to remove UserRepositoryInterface::getRolesFromUser()

public function getRolesFromUser(string $identity) : array;

I'm wondering why that is added to the interface. Since the roles are added to an authenticated user, it's only needed internally to retrieve the roles in certain situations. E.g. the included PdoDatabase Repository uses it. But if you use doctrine and have the roles added as a relation, it's already included for you. Also Htpasswd doesn't have roles.

Also the authorization module doesn't use it as it gets the roles from the User object.

Accent not supported in result of sql_get_roles or sql_get_details in authentication process session

Hi,

This problem appear in login process in the AuthenticationMiddleware. I have a table "users" with
some fields like user_id | username | password | firstname | email | role | create_date

PHP 7.1.20-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Jul 25 2018 10:06:40) ( NTS )

In the authentication config i have:
... 'driver_options' => [ PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' ], 'sql_get_roles' => 'SELECT role FROM users WHERE username = :identity', 'sql_get_details' => 'SELECT user_id,firstname FROM users WHERE username=:identity' ...

All works fine if the content of "firstname" or "role" have no accent and i can access to my app without problem BUT when by example i enter the firstname "Valérie" (something with a accent) in the firstname field (or role), the login process hang (500) (see all errors below) and i must erase cookie to return to the login page (login is impossible).

`expressive/vendor/zendframework/zend-expressive-session/src/Session.php

     */
    private $originalData;
 
    public function __construct(array $data)
    {
        $this->data = $this->originalData = $data;
    }
 
    /**
     * Convert a value to a JSON-serializable value.
     *
     * This value should be used by `set()` operations to ensure that the values
     * within a session are serializable across any session adapter.
     *
     * @param mixed $value
     * @return null|bool|int|float|string|array|\stdClass
     */
    public static function extractSerializableValue($value)
    {
        **return json_decode(json_encode($value, \JSON_PRESERVE_ZERO_FRACTION), true);**
    }`

It indicate me that line in bold (return json_decode(....), i suppose that it have a utf8 problem somewhere...

Code to reproduce the issue

It is just the normal process for authentication found in the docs.

Expected results

Just allowing words with accent (sql_get_details, sql_get_roles)

Actual results

TypeError thrown with message "json_decode() expects parameter 1 to be string, boolean given"

Stacktrace:
#50 TypeError in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-session/src/Session.php:49
#49 json_decode in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-session/src/Session.php:49
#48 Zend\Expressive\Session\Session:extractSerializableValue in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-session/src/Session.php:79
#47 Zend\Expressive\Session\Session:set in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-session/src/LazySession.php:75
#46 Zend\Expressive\Session\LazySession:set in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-authentication-session/src/PhpSession.php:106
#45 Zend\Expressive\Authentication\Session\PhpSession:authenticate in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-authentication/src/AuthenticationMiddleware.php:34
#44 Zend\Expressive\Authentication\AuthenticationMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:46
#43 Zend\Expressive\Middleware\LazyLoadingMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/Next.php:52
#42 Zend\Stratigility\Next:handle in /home/michael/dev/test-app/expressive/src/App/src/Handler/LoginHandler.php:69
#41 App\Handler\LoginHandler:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:46
#40 Zend\Expressive\Middleware\LazyLoadingMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/Next.php:52
#39 Zend\Stratigility\Next:handle in /home/michael/dev/test-app/expressive/src/App/src/Middleware/PrgMiddleware.php:39
#38 App\Middleware\PrgMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:46
#37 Zend\Expressive\Middleware\LazyLoadingMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/Next.php:52
#36 Zend\Stratigility\Next:handle in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-csrf/src/CsrfMiddleware.php:52
#35 Zend\Expressive\Csrf\CsrfMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:46
#34 Zend\Expressive\Middleware\LazyLoadingMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/Next.php:52
#33 Zend\Stratigility\Next:handle in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/MiddlewarePipe.php:91
#32 Zend\Stratigility\MiddlewarePipe:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-router/src/Route.php:100
#31 Zend\Expressive\Router\Route:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-router/src/RouteResult.php:110
#30 Zend\Expressive\Router\RouteResult:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-router/src/Middleware/DispatchMiddleware.php:35
#29 Zend\Expressive\Router\Middleware\DispatchMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:46
#28 Zend\Expressive\Middleware\LazyLoadingMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/MiddlewarePipe.php:78
#27 Zend\Stratigility\MiddlewarePipe:handle in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-helpers/src/UrlHelperMiddleware.php:45
#26 Zend\Expressive\Helper\UrlHelperMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:46
#25 Zend\Expressive\Middleware\LazyLoadingMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/MiddlewarePipe.php:78
#24 Zend\Stratigility\MiddlewarePipe:handle in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-router/src/Middleware/MethodNotAllowedMiddleware.php:51
#23 Zend\Expressive\Router\Middleware\MethodNotAllowedMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:46
#22 Zend\Expressive\Middleware\LazyLoadingMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/MiddlewarePipe.php:78
#21 Zend\Stratigility\MiddlewarePipe:handle in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-router/src/Middleware/ImplicitOptionsMiddleware.php:70
#20 Zend\Expressive\Router\Middleware\ImplicitOptionsMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:46
#19 Zend\Expressive\Middleware\LazyLoadingMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/MiddlewarePipe.php:78
#18 Zend\Stratigility\MiddlewarePipe:handle in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-router/src/Middleware/ImplicitHeadMiddleware.php:84
#17 Zend\Expressive\Router\Middleware\ImplicitHeadMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:46
#16 Zend\Expressive\Middleware\LazyLoadingMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/MiddlewarePipe.php:78
#15 Zend\Stratigility\MiddlewarePipe:handle in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-router/src/Middleware/RouteMiddleware.php:54
#14 Zend\Expressive\Router\Middleware\RouteMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:46
#13 Zend\Expressive\Middleware\LazyLoadingMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/MiddlewarePipe.php:78
#12 Zend\Stratigility\MiddlewarePipe:handle in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-session/src/SessionMiddleware.php:34
#11 Zend\Expressive\Session\SessionMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:46
#10 Zend\Expressive\Middleware\LazyLoadingMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/MiddlewarePipe.php:78
#9 Zend\Stratigility\MiddlewarePipe:handle in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive-helpers/src/ServerUrlMiddleware.php:37
#8 Zend\Expressive\Helper\ServerUrlMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:46
#7 Zend\Expressive\Middleware\LazyLoadingMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/MiddlewarePipe.php:78
#6 Zend\Stratigility\MiddlewarePipe:handle in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/Middleware/ErrorHandler.php:143
#5 Zend\Stratigility\Middleware\ErrorHandler:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:46
#4 Zend\Expressive\Middleware\LazyLoadingMiddleware:process in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-stratigility/src/MiddlewarePipe.php:78
#3 Zend\Stratigility\MiddlewarePipe:handle in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-httphandlerrunner/src/RequestHandlerRunner.php:95
#2 Zend\HttpHandlerRunner\RequestHandlerRunner:run in /home/michael/dev/test-app/expressive/vendor/zendframework/zend-expressive/src/Application.php:81
#1 Zend\Expressive\Application:run in /home/michael/dev/test-app/expressive/public/index.php:29
#0 {closure} in /home/michael/dev/test-app/expressive/public/index.php:30

Change username to identity

I'm trying to implement this in a system that doesn't have unique usernames (only real names). It has userId's and unique email addresses though. However implementing the UserInterface with getUsername() doesn't make sense if it returns the id or email address.

To me it makes more sense to have something less strict like this:

interface UserInterface
{
    /**
     * Get the unique user identity (id, username, email address or ...)
     */
    public function getIdentity() : string;

    /**
     * Get all user roles
     *
     * @return string[]
     */
    public function getUserRoles() : array;
}

Readme: still not meant for production?

I was wondering if this is still not meant to be used in production, since there haven't been any big code changes in the last 3 months.

I'm planning to use this middleware for two projects.
I haven't experienced anything that's preventing me to use this in production, except your hint in the readme.

(And the fact, that I'm getting my head ripped off, I there are errors and they find out I have been warned.)

Wrong config parameter name in the \Zend\Expressive\Authentication\UserRepositoryPdoDatabaseFactory factory

@weierophinney

Good morning,

There is a wrong configuration parameter name in the \Zend\Expressive\Authentication\UserRepositoryPdoDatabaseFactory factory:

...
        if (null === $pdo) {
            throw new Exception\InvalidConfigException(
                'PDO values are missing in user_register config'
            );
        }
...

should be

...
        if (null === $pdo) {
            throw new Exception\InvalidConfigException(
                'PDO values are missing in authentication config'
            );
        }
...

Thank you.

propose to AuthenticationInterface

Hi, I'm migrate Silex to Expressive on my work.

I was read the authentication code I think AuthenticationInterface could have just the method public function authenticate(ServerRequestInterface $request) : UserInterface and throw exception when do not have any match.

I can implementation like this

class AuthenticationMiddleware implements MiddlewareInterface
{
    /**
     * @var AuthenticationInterface
     */
    private $auth;

    public function __construct(AuthenticationInterface $auth)
    {
        $this->auth = $auth;
    }

    /**
     * {@inheritDoc}
     */
    public function process(ServerRequestInterface $request, DelegateInterface $delegate)
    {
        try {
            return $delegate->process($request->withAttribute(UserInterface::class, $this->auth->authenticate($request)));
        } catch (Exception\BadRequestException $e) {
            return new Response('php://temp', StatusCode::STATUS_BAD_REQUEST);
        } catch (Exception\UnauthorizedException $e) {
            return new Response('php://temp', StatusCode::STATUS_UNAUTHORIZED);
        }
    }
}
class BearerAuthentication implements AuthenticationInterface
{
    public function authenticate(ServerRequestInterface $request): UserInterface
    {
        if (false === ($header = $request->getHeaderLine('Authorization') ?: false)) {
            throw new BadRequestException;
        }

        if (!preg_match('/Bearer\s(\S+)/', $header, $matches)) {
            throw new BadRequestException;
        }
        
        // ....
        
        throw new UnauthorizedException;
    }
}

What do you think?

Is getUserRole() necessary?

Why does the UserInterface need a getUserRole() method? What if my authorization system doesn't use roles?

The \Zend\Expressive\Authentication\UserRepositoryPdoDatabaseFactory factory should accept PDO instance

@weierophinney

Good morning,

Right now, the \Zend\Expressive\Authentication\UserRepositoryPdoDatabaseFactory factory force us to provide whole configuration set for PDO. Most of time, we will have our own factory returning a PDO instance already. It could be great if the \Zend\Expressive\Authentication\UserRepositoryPdoDatabaseFactory factory accept a service name for the PDO, or even a PDO instance.

Thank you.

Unable to extend PdoDatabase user repository implementation

Continued from slack...

I'd like to extend UserRepository\PdoDatabase since the password_verify function does not meet our needs for legacy password hash verification.

Additionally, we have a flag in the db for a user to indicate whether the user is "active". We'd like to return null in the event that the user is not "active".

Code to reproduce the issue

namespace MyNamespace;

use Zend\Expressive\Authentication\UserRepository\PdoDatabase;
use Zend\Expressive\Authentication\UserInterface;

class MyUserRepository extends PdoDatabase
{

    public function authenticate(string $credential, string $password = null): ?UserInterface
    {
        // do anything with $this->config
        var_dump($this->config);
    }
}

Expected results

I expect to be able to access $this->config property (as well as $this->pdo and $this->userFactory) in an extension.

Actual results

Undefined property: MyNamespace\MyUserRepository::$config

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.