Giter VIP home page Giter VIP logo

authentication's Introduction

CakePHP Authentication

Build Status Latest Stable Version Total Downloads Code Coverage Software License

PSR7 Middleware authentication stack for the CakePHP framework.

Don't know what middleware is? Check the CakePHP documentation and additionally read this.

Authentication, not Authorization

This plugin intends to provide a framework around authentication and user identification. Authorization is a separate concern that has been packaged into a separate authorization plugin.

Installation

You can install this plugin into your CakePHP application using composer:

php composer.phar require cakephp/authentication

Load the plugin by adding the following statement in your project's src/Application.php:

public function bootstrap(): void
{
    parent::bootstrap();

    $this->addPlugin('Authentication');
}

Documentation

Documentation for this plugin can be found in the CakePHP Cookbook.

IDE compatibility improvements

For AuthenticationService::loadIdentifier() you an find an IdeHelper task in IdeHelperExtra plugin.

authentication's People

Contributors

admad avatar ajibarra avatar andrii-pukhalevych avatar arhell avatar burzum avatar cleptric avatar cnizzardini avatar dependabot[bot] avatar dereuromark avatar enviniom avatar floriankraemer avatar grandfelix avatar inoas avatar jeremyharris avatar josegonzalez avatar lordsimal avatar markstory avatar mr-ijij avatar ndm2 avatar othercorey avatar peter279k avatar ravage84 avatar riteshparyali avatar robertpustulka avatar rochamarcelo avatar saeideng avatar stickler-ci avatar swiffer avatar zachee54 avatar zuluru avatar

Stargazers

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

authentication's Issues

Improve identifier errors

Currently, when an Identifier can't find a user, it just returns null, which leads into an error array with no explanation of what went wrong in the return of authenticate().

[
    'Authentication.Orm' => []
]

Maybe we can add sth like:

[
    'Authentication.Token' => [],
    'Authentication.Orm' => [
        'No user was found' // e.g.
    ]
]

RFC: Setup authentication through method calling (bonus fluent interface)

Reason

I would love to see stuff to fail early. It should be easy to know where and why. The current array configuration is maybe a bit error-prone and fails silently.

I would love to be notified when something is wrong and right now when you pass some array structure that is malformed it is silently ignored and I think it would save countless hours if you were notified.

The current array-based configuration also adds a lot of newbie questions on the social channels that could be caught early with this feature!

Suggestion

Could an interface like this work (and/or be improved)?:

class Application extends BaseApplication
{
    public function middleware($middleware)
    {
        // Instantiate the authentication service and configure authenticators
        $service = new AuthenticationService()
            ->addIdentifier('Orm'),
            // TODO handle assignments - like username, password, finders (scopes) - here
            ->addAuthenticator('Form')
            ->addAuthenticator('Session');

        // Add it to the authentication middleware
        $authentication = new AuthenticationMiddleware($service);

        // Add the middleware to the middleware stack
        $middleware->add($authentication);
    }
}

RFC - Change file organization

Not really happy with the way files / namespace are organized. Would much prefer to have them similar to what's shown below:

src/
    Identifier/
        IdentifierCollection.php
        IdentifierInterface.php
        AbstractIdentifier.php
        ...
    Adapter/
        AdapterInterface.php
        AbstractAdapter.php
        FormAdapter.php
        ...
    PasswordHasher/
        PasswordHasherFactory.php
        PasswordHasherTrait.php
        AbstractPasswordHasher.php
        ...
    Result.php
    ResultInterface.php
    AuthenticationService.php

RFC: Default sessionKey is not BC compatible

The old auth system used Auth.User or Auth.<modelAsSingular> but the default in the new SessionAuthenticator is just Auth. This causes problems when you're still using the old AuthComponent and it's authorization part.

In our case I try to migrate the existing apps AuthComponent to the new plugin but running into trouble with exactly the above.

This can be fixed / worked around by configuring it:

$service->loadAuthenticator('Authentication.Session', [
    'sessionKey' => 'Auth.User'
]);

Do we want to make this BC at all out of the box?

Should the authenticator handle expired or otherwise invalid JSON Web Tokens?

I've started implementing an API with CakePHP that uses JSON Web Tokens, and upon testing handling expired or otherwise invalid tokens, I've noticed that in non-debug mode this will cause CakePHP to respond with a generic 500 error, as the JWT::decode() call in JwtAuthenticator::decodeToken() will throw an exception that isn't being handled.

{
	"message": "An Internal Error Has Occurred.",
	"url": "\/api\/v1.0\/account\/info",
	"code": 500
}

I'd like to have a more graceful handling of such "errors", I'd like to be able to inspect the authentication result and respond with a "soft" 401 in such cases, alongside with a message and/or code for the client to evaluate, so that it can present meaningful information to the user.

I'm currently extending JwtAuthenticator, overriding JwtAuthenticator::authenticate() to catch the exception(s) and prepare a result accordingly, but I'm wondering whether this is maybe something that JwtAuthenticator should be able to somehow handle out of the box?

Callbacks for afterLogin/afterSetIdentity, beforeLogout/beforeClearIdentity?

Without digging too much into the code, just looking at the docs:

  • Is it already possible to run custom code on callbacks: after-login/after-set-identity (stateful/stateless), before-logout/before-clear-identity? (stateful only)
  • If not would you deem it worthwhile?
  • Example applications: update last_login_datetime, log failed and successful user sign-in attempts, log user sign-outs

Documentation Gaps

For users migrating from AuthComponent there are some big questions that are not answered by the documentation:

  1. How do you log in?
  2. How do restrict access to actions in a controller (like you do with $this->Auth->allow())?
  3. How do you redirect to the login page when users are not logged in?

It would be helpful to have a version of the Authentication and Authorization Blog Tutorial using this middleware instead of AuthComponent.

Adding a JWT token authenticator

JWT is pretty common these days and I think we should provide out of the box support for it.

This should be very easy to do with the already existing basic token authenticator. Just extend it and use a JWT lib. The question is which JWT lib do we want to use? We clearly don't want to reinvent the wheel.

Here is a list of libs, go down to php https://jwt.io/

Authentiator and Identifier collection/registry upgrade.

Currently loading identifiers slightly differs from loading authenticators.

While loadAuthenticator() behaves more CakePHP-way accepting className option, loadIdentifier() treats a first argument as a class name, and accepts alias option. I think this should be refactored to behave the same way as core registries do.

I've been also thinking about some way to add Authenticator and Identifiers instances. Currently these can only be loaded from config. There's also no way to unset an object. Another thing is that identifiers have a collection but authenticators are stored in an array in AuthenticationService. Maybe both types of objects should share the same API for managing collections?

Example:

$service->loadAuthenticator('Form');
//or
$service->authenticators()->load('Form');
//or
$authenticator = new FormAuthenticator();
$service->authenticators()->set('Form', $authenticator);
//and then at some point:
$service->authenticators()->unset('Form');

TODO:

  • Rename AuthenticateInterface to AuthenticatorInterface (#105)
  • Create common collection for authenticators and identifiers
  • Implement subject specific collections
  • Add AuthenticationServiceInterface::loadIdentifier()

clearIdentity : Purpose of Response

Hi,

I would like to know what is the purpose of clearIdentity(ServerRequestInterface $request, ResponseInterface $response); method.

I have been looking into the code and don't see any changes happening to response object.

Eg :

public function clearIdentity(ServerRequestInterface $request, ResponseInterface $response)

Digged the rest of the classes via a search : https://github.com/cakephp/authentication/search?utf8=%E2%9C%93&q=clearIdentity

I think returning only Request is needed if response object is not altered .

Authentication Service is overriding original error

Correct me if I am wrong, but I was looking into why my authentication error code was not being returned correctly and I noticed that in the AuthenticationService class the result is being overridden before being returned.

 public function authenticate(ServerRequestInterface $request, ResponseInterface $response)
{
    $this->loadAuthenticators();

    foreach ($this->_authenticators as $authenticator) {
        $result = $authenticator->authenticate($request, $response);
        if ($result->isValid()) {
            if ($authenticator instanceof PersistenceInterface) {
                $authenticator->persistIdentity(
                    $request,
                    $response,
                    $result->getIdentity()
                );
            }

            $this->_successfulAuthenticator = $authenticator;

            return $this->_result = $result;
        }
        if (!$result->isValid() && $authenticator instanceof StatelessInterface) {
            $authenticator->unauthorizedChallenge($request);
        }
    }

    $this->_successfulAuthenticator = null;
    $this->_result = $result;

    return $this->_result = new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND);
}

Was this left over debugging? If not, then what is the purpose of the line above it to set the result?

Datasource backend proposal.

In #109 "backend" idea was introduced. I was wondering if we could transform this idea into kind of a pattern.

Currently both OrmIdentifier and TokenIdentifier (and identifiers that extend it) depend on ORM but do it differently. OrmIdentifier is an identifier build especially for identifying users by password using CakePHP ORM. TokenIdentifier can be extended and use other methods of token verification. Implementations differ but the idea is the same: query the ORM (or any other datasource) with given conditions (username/password or token) and return an identity (EntityInterface in this case).

I was thinking we could enhance this and make it easier to integrate with other ORMs.

My idea is to add Authentication\Identifier\Backend\DatasourceInterface:

interface DatasourceInterface {
    //return value should be ArrayAccess instead of cake EntityInterface
    public function find(array $conditions): ArrayAccess;
}

And implement it for our ORM:

//draft implementation
class OrmBackend implements DatasourceInterface {
    public function find(array $conditions) {
        return $this->table->find()->where($conditions)->first();
    }
}

Now both OrmIdentifier and TokenIdentifier could use this in order to query an identity from database (or any other datasource).

For example:

//TokenIdentifier
$identity = $this->backend->find([$tokenField => $token]);
...
//OrmIdentifier
$identity = $this->backend->find([$usernameField => $username]);
//password check etc
...

Developers could implement adapters (backends) for custom ORMs and still use those identifier classes.

I think OrmIdentifier should be then renamed to PasswordIdentifier to better reflect what this does since it would no longer be ORM dependent.

Add a LDAP identifier?

It would a very easy to turn this plugin into an identifier. Let's do it?

I just don't have a LDAP server I could test against it. I have no idea how to test the function calls either. A possibility would be a small OOP wrapper around the modules functions and mock the whole LDAP connection object.

Authentication component? Needed? Features?

This could be done as a convenience way to access the service in the request:

class AuthenticationComponent extends Component {

    public function logout()
    {
        $controller = $this->_registry->getController();
        $authentication = $controller->request->getAttribute('authentication');
        if (!$authentication instanceOf AuthenticationService) {
            // Just return or throw exception?
            return;
        }

        $result = $authentication->clearIdentity(
            $controller->request,
            $controller->response
        );

        $controller->request = $result['request'];
        $controller->response = $result['response'];
    }
}

We could get the user as well but we can't write to the persistent authenticators through the service yet. So do we want to implement that at all? Also the component would give us a way to implement events like afterLogin we currently don't have but the old AuthComponent has.

If we implement methods to get and set the user data I would suggest to call them getUser and setUser.

Question: Is the changed instance of $controller->request and the response going to be available in the view layer as well? Or won't make this the way down to the view?

userModel not working?

Apologies for putting this here, unfortunatly I have no idea where else to ask.

I have the following method:

    public function middleware($middlewareQueue)
    {

        // Authentication block
        $service = new AuthenticationService();
        $fields = [
            'username' => 'login',
            'password' => 'password',
        ];
        $service->loadIdentifier('Authentication.Password', [
            'userModel' => 'Employees',
            'fields' => [
                'username' => 'login',
                'password' => 'password',
            ],
        ]);
        $service->loadAuthenticator('Authentication.Session');
        $service->loadAuthenticator('Authentication.Form', [
            'fields' => $fields,
            'loginUrl' => [
                'plugin' => false,
                'controller' => 'Employees',
                'action' => 'login',
            ],
            'userModel' => 'Employees'
        ]);
        
        $middlewareQueue
            ->add(new AuthenticationMiddleware($service))
            // Catch any exceptions in the lower layers,
            // and make an error page/response
            ->add(ErrorHandlerMiddleware::class)
            // Handle plugin/theme assets like CakePHP normally does.
            ->add(AssetMiddleware::class)
            // Add routing middleware.
            ->add(new RoutingMiddleware($this));

        return $middlewareQueue;
    }

However when running this it just complains it cant find a Users table, am I doing something wrong?

Unfortunately, It doesn't seem to say where to put the userModel setting in the documentation.

Catchable authentication failures

Apologies in advance if this is outside of scope for the plugin.

Use-case

I log access to my api into a datastore for various reasons, using my ApiMiddleware. I'd like to log if the request was successful or not, as well as other details about what the request is.

Hooking the Authentication middleware

Am I able to hook the authentication middleware to see if a response from the auth middleware layer was successfull or not?

Or do I have to build the response in my custom authorize() method and return a built response from there with some stuff set which my ApiMiddleware can pickup?

Using both Orm and Token identifiers

What am I doing?

I'd like to use different Authentication for my CMS than my API. Previously I'd configure different AuthComponent setups in my AppController, v3/ApiAppController and v4/ApiAppController.

What did I do?

$service = new AuthenticationService();
$service->loadIdentifier('Authentication.Orm', [
    'fields' => [
        'username' => 'email',
        'password' => 'password'
    ],
    'userModel' => 'Users',
    'finder' => 'auth',
]);
$service->loadIdentifier('Authentication.Token', [
    'tokenField' => 'keycode',
//  'dataField' => '_token', // I'm not actually sure what this is supposed to be
    'userModel' => 'ApiUsers',
    'finder' => 'all',
    'tokenVerification' => 'Orm'
]);

$service->loadAuthenticator('Authentication.Session', [
    'sessionKey' => 'user'
]);
$service->loadAuthenticator('Authentication.Form', [
    'fields' => [
        'username' => 'email',
        'password' => 'password'
    ]
]);
$service->loadAuthenticator('Authentication.Token', [
    'header' => 'X-ApiToken',
    'queryParam' => '_token',
    'tokenPrefix' => null,
]);

$authentication = new AuthenticationMiddleware($service);
$middleware->add($authentication);

What happened?

Database Error, PDOException
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Users.keycode' in 'where clause'

What's going on?

I think that perhaps because I've specified Orm as the tokenVerification it's using the settings from the Orm identifier, and looking for the ApiUsers.keycode in the Users table.

FormAuthenticator checks for username password for every request

Currently the FormAuthenticator checks for username password for every request which is undesirable. It would be especially problematic for example for a registration form. Since it would find the username and password in POST data it would automatically log in. Ideally the one should be able to configure a login URL and the authenticator should check for the fields only for that URL.

Add isStateless() to the authenticators?

This would be useful because some use cases rely on if an authentication was done stateless or not. One use case for example is to fire the afterIdentify even. We wan't to fire that only on a first time login (via form and HTTP POST for example) and not each time a token gets verified and "logged in".

So I would add isStateless() to the AuthenticateInterface.

Please change the dependency to a release

If you are releasing betas, please do change the dependencies to make use of beta versions.

https://github.com/cakephp/authentication/blob/1.0.0-beta1/composer.json#L12-L15

"cakephp/core": "dev-3.next as 3.4",
"cakephp/event": "dev-3.next as 3.4",
"cakephp/orm": "dev-3.next as 3.4",
"cakephp/utility": "dev-3.next as 3.4",

else

{
    "require": {
        "cakephp/authentication":"~1.0"
    },
    "minimum-stability":"beta"
}

releases are not useful for it dumps

composer install
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for cakephp/authentication ~1.0 -> satisfiable by cakephp/authentication[1.0.0-beta1].
    - cakephp/authentication 1.0.0-beta1 requires cakephp/core dev-3.next as 3.4 -> satisfiable by cakephp/core[dev-3.next] but these conflict with your requirements or minimum-stability.

The work around I know is use something like

"cakephp/authentication":"dev-master",
"cakephp/core": "dev-3.next as 3.4",
"cakephp/event": "dev-3.next as 3.4",
"cakephp/orm": "dev-3.next as 3.4",
"cakephp/utility": "dev-3.next as 3.4",

but again then these tags are not useful in its own.

[RFC] Add authentication hook for application

I was thinking how the authentication could be configured in a more clean way. Currently we suggest to configure authentication in middleware hook, but the method could become too large and harder to maintain as the application grows.

One of the options is to have a dedicated application hook similar to the console, middleware or routes.

This is how it could look like:

    public function authentication($authentication)
    {
        $authentication->loadIdentifier('Authentication.Password');
        $authentication->loadAuthenticator('Authentication.Session');
        $authentication->loadAuthenticator('Authentication.Form');

        return $authentication;
    }

    public function middleware($middleware)
    {
        $middleware
            ->add(ErrorHandlerMiddleware::class)
            ->add(AssetMiddleware::class)
            ->add(new RoutingMiddleware($this))
            ->add(new AuthenticationMiddleware($this));

        return $middleware;
    }

The AuthenticationService could be configured in a hook and the application instance could be passed to the AuthenticationMiddleware.

Sometimes different authentication is needed for different scopes. This could be achieved with named authentication services.

    public function authentication($authentication)
    {
        $authentication->loadIdentifier('Authentication.Password');
        $authentication->loadAuthenticator('Authentication.Session');
        $authentication->loadAuthenticator('Authentication.Form');

        return $authentication;
    }

    public function authenticationApi($authentication)
    {
        $authentication->loadIdentifier('Authentication.Token');
        $authentication->loadAuthenticator('Authentication.Token');

        return $authentication;
    }

    public function routes($routes)
    {
        $routes->registerMiddleware('auth', new AuthenticationMiddleware($this));
        $routes->registerMiddleware('apiAuth', new AuthenticationMiddleware($this, 'api'));

        $routes->scope('/', function (RouteBuilder $routes) {
            $routes->applyMiddleware('auth');
        });

        $routes->scope('/api', function (RouteBuilder $routes) {
            $routes->applyMiddleware('apiAuth');
        });
    }

    public function middleware($middleware)
    {
        $middleware
            ->add(ErrorHandlerMiddleware::class)
            ->add(AssetMiddleware::class)
            ->add(new RoutingMiddleware($this));

        return $middleware;
    }

I think this looks cleaner and better structured than having all configuration in one method.

Credential challenge headers not sent to client for HttpBasic and HttpDigest authenticators

While the authenticator for http basic and digest authenticator have unauthenticated() method for throwing UnauthorizedException with the challenge headers this method is never called by the authentication service.

Similarly for other stateless authenticator like TokenAuthenticator there's no mechanism to return a response with 401 code. So even if authentication fails the controller action is accessible.

Adding a callback identifier?

This would allow people to quickly come up with simple identifier solutions. For example I have a simple academic data uploader app and my friend is the only "user" and so I'm just checking against a password coming from the apps config. Could work nice for prototyping as well.

Edit: PR is up. :) #60

Allow OrmIdentifier to identify using any one field from a provided list.

A common use case is allowing users to login using either their username or email. It would be nice if OrmIdentifier could cater to this scenario out of the box. One way would be allow the 'username' option to take an array like ['username', 'email'] and the code then craft the db query accordingly.

Add a Token authenticator?

It's pretty common these days to work with APIs that have a token.

  • Look in the header for a token like JWT
  • Look in the request query params for a token
  • Allow a callback for the token extraction from the request
  • Add an OrmToken identifier

The only thing somebody would have to do in this case for the JWT token is to implement a JWT token identifier. We could provide it as well and suggest the JWT lib in the composer.json. JWT out of the box would be nice.

Add it or not? :)

How would one logout user?

Currently there's no mechanism to clear the identity stored in session so how would one handle user logout? It would be wrong to expect user to directly clear identity from session using request->session().

Rename config "verifyByDatabase" to "identify"

It would be more appropriate to rename the "verifyByDatabase" config used in SessionAuthenticator to "identify" since the identification depends upon the configured identifiers, doesn't necessarily have to be db based only.

FormAuthenticator::_checkLoginUrl() fails when accessing alternative route

For testing I've been accessing the direct controller/action URL http://cake3.world-architects.com/en/users/login but we have a route for that as well /en/login.

But the FormAuthenticator compares only a string URL and not if the passed array really matches the resolved controller action but instead only the first route that machtes:

\vendor\cakephp\authentication\src\Authenticator\FormAuthenticator.php (line 71)
'/en/users/login'
\vendor\cakephp\authentication\src\Authenticator\FormAuthenticator.php (line 72)
'/en/login'

I'm not sure if there is a better way than to compare the arrays to resolve this?

Make empty() checks explicit

if (empty($data) && $code === self::SUCCESS) {

I really do not like the use of weak empty() I am always uncertain what types there are ok and which are not.

Could we make this more explicit? Could the core authors say a word about what kind of data structure there should be in $data? Maybe we should even check against some array_key_exists?

SessionAuthenticator identify option does not work.

I set up authentication as below:

    public function authentication(AuthenticationServiceInterface $authentication)
    {
        $authentication->loadIdentifier('Authentication.Password');

        $authentication->loadAuthenticator('Authentication.Session', [
            'identify' => true
        ]);
        $authentication->loadAuthenticator('Authentication.Form');

        return $authentication;
    }

Identity verification won't work. SessionAuthenticator assumes that the data persisted in session provides a plain text password: https://github.com/cakephp/authentication/blob/master/src/Authenticator/SessionAuthenticator.php#L60-L63

We need an alternative approach to reidentify the identity since we can't expect that stored identity data will provide plain text password for identifiers.

This will be needed for the CookieAuthenticator as well.

Rename plugin to cakephp/authentication

Shouldnt the whole plugin then be renamed from

cakephp/middleware-authentication

to

cakephp/authentication

?

I mean Middleware is a specific pattern and implementation detail that does not need to be reflected in the name. How it is done internally should not matter to "what it does" which should be reflected in the name.

Refs #9

When failing to authenticate Results errors is empty

What I did

Setup my middleware as per the docs, and then tried to authenticate with invalid credentials.

What happened

The middleware set the attribute in the request

What I tried to do

I wanted to get the reason why it failed with $request->getAttribute('authentication')->getResult()->getErrors().

What I expected to happen

I would assume that it'd return a string reason for the -1 response code, which is FAILURE_IDENTITY_NOT_FOUND. So something like 'Unable to identify' or similar.

What actually happened

I got an array with just the authenticators as a key and no string errors.

object(Authentication\Result)[177]
  protected '_code' => int -1
  protected '_identity' => null
  protected '_errors' => 
    array (size=2)
      'Authentication.Orm' => 
        array (size=0)
          empty
      'Authentication.Token' => 
        array (size=0)
          empty

Code

It seems that the identifier isn't returning any errors to pass through to the result.
https://github.com/cakephp/authentication/blob/master/src/Authenticator/TokenAuthenticator.php#L116

public function identify($data)

This method should not @return false|EntityInterface but instead @return EntityInterface|null.
It is a cleaner default value in general (despite the fact that this should be "bool", not "false", as false doesnt exist as type).
Also, this would be future compliant with 7.1+ "nullable" strictness, if we ever introduced that.

It is also more consistent with the rest of the framework or the direction it goes to, or where it should go to - either using a NullObject of some sorts or just returning null.
Using more than that as return type alternatives is usually a code smell - and a clear nogo even when returning objects.

Feedback: Status Codes

About the Status Codes:

    1: Success (Result::SUCCESS)
    0: Failure (Result::FAILURE)
    -1: Identify not found (Result::FAILURE_IDENTITY_NOT_FOUND)
    -2: Credentials invalid (Result::FAILURE_CREDENTIAL_INVALID)
    -3: Any other kind of failure (Result::FAILURE_OTHER)
    -4: Credentials not found (Result::FAILURE_CREDENTIALS_NOT_FOUND)

The numbers are weird ...

  • There are no holes to add more inbetween or have them grouped
  • Working with negative status codes makes stuff harder to work with as you cannot easily use strpos
  • They do not follow posix-style or http-style (why not one of them?)
  • They are ordered strange... identity not found > credentials not found > credentials invalid > any other failure or so would make more sense.
  • This shows PHP misses atoms :(.

Homogeneous api for identifiers and authenticators

Why don't identifiers and authenticators get loaded on a similar way? I mean, the use case it's pretty much the same: to load a class (optionally with its config) into a stack/set of elements. If you take a look into its load methods and are pretty similar...

Right now we have:

        // Load identifiers
        $service->identifiers()->load('Authentication.Orm', [
            'fields' => [
                'username' => 'email',
                'password' => 'password'
            ]
        ]);

        // Load the authenticators, you want session first
        $service->loadAuthenticator('Authentication.Session');
        $service->loadAuthenticator('Authentication.Form');

I wonder why don't we have same way on both:

        // Load identifiers
        $service->identifiers()->load('Authentication.Orm', [/*...config...*/]);

        // Load the authenticators, you want session first
        $service->authenticators()->load('Authentication.Session', [/*...config...*/]);
        $service->authenticators()->load('Authentication.Form'); // without config

or:

        // Load identifiers
        $service->loadIdentifier('Authentication.Orm', [/*...config...*/]);

        // Load the authenticators, you want session first
        $service->loadAuthenticator('Authentication.Session', [/*...config...*/]);
        $service->loadAuthenticator('Authentication.Form'); // without config

I guess it's more a question than a bug, but I just noticed that and wanted to let you know. I think that will be easier to learn/remember an api when things are done in a "standard" way.

Add ability to know which authenticator suceeded.

The AuthComponent allows you to get instance of authenticator which succeeded in authenticating the user using authenticationProvider() method. Would be nice to have similar featured in AuthenticationService too.

[RFC] Identity abstraction

IIRC we decided that ArrayAccess for identity abstraction would suffice. It would allow for using EntityInterface instances as identities.

I noticed that there's still IdentityInterface and Identity class in use. It looks like a wrapper for a ArrayAccess an actual identity returned from a successfull authenticator result.

I'm wondering if that's even necessary given the fact, that the actual identity passed to the request parameter will be an IdentityInterface instance rather than an entity or whatever returned from an identity resolver. The whole idea of having flexible interface (ArrayAccess) for identities falls through. The IdentityInterface doesn't even have a method to access the original identity.

My idea is to get rid of IdentityInterface and Identity at all and use actual identities as request parameters. The interface and the class look reduntant to me.

Disabling authentication for certain actions.

I'm wondering how can I make some controllers/actions public?

Currently after adding AuthenticationMiddleware all requests have to be authenticated. The only exception is for login url in FormAuthenticator. But there are some use cases like home page etc, where authentication is not necessary.

I know this plugin intends to decouple authorization from authentication but my use case takes place before authorization is even possible. I want to have actions not authenticated at all.

In AuthComponent we had allow() and deny() to control when authentication should take place. Now this feature is missing.

AuthenticationComponent::logout

The AuthenticationComponent::logout() currently transforms the request and response into an array, which will break afterwards, if you call $this->redirect() in a controller.

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.