Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auth Middleware #38

Open
trenggana-klb opened this issue Aug 28, 2019 · 9 comments
Open

Auth Middleware #38

trenggana-klb opened this issue Aug 28, 2019 · 9 comments

Comments

@trenggana-klb
Copy link

Hi @adhocore,
I really like this phalcon-ext and try to use for my new journey with phalcon
I have question about how to implement the ApiAuth Middleware on micro app
I already try it, but why always return Permission denied for all my defined route.

Here are my snippets code

config.php
--------------

// The permission scopes required for a route
        'scopes' => [
            /'validation' => 'user',
        ],
index.php
-------------
<?php

use PhalconExt\Http\Middlewares;
use PhalconExt\Http\Middleware\ApiAuth;
use PhalconExt\Http\Middleware\Cache;
use PhalconExt\Http\Middleware\Cors;
use PhalconExt\Http\Middleware\Throttle;
use Phalcon\Http\Response;
use Phalcon\Mvc\Micro as MicroApplication;
use Phalcon\Mvc\Micro\Collection;
use Phalcon\Mvc\Router;
use Vinculum\Controller\MicroController;

// Micro app
$di = require __DIR__ . '/../app/bootstrap.php';

$app = new MicroApplication($di);

$app->getRouter()->setUriSource(Router::URI_SOURCE_GET_URL);

$app->mount((new Collection)
        ->setPrefix('/')
        ->setHandler(MicroController::class, true)
        ->get('/', 'indexAction', 'home')
        ->get('validation', 'validationAction')
        ->post('api/auth', 'authAction')
);

$app->notFound(function () {
    $data = [
        'code' => 404,
        'status' => 'not_found',
        'message' => 'Page not found',
    ];
    $response = new Response();
    return $response->setJsonContent($data)->setStatusCode(404);
});

(new Middlewares([Throttle::class, ApiAuth::class, Cors::class, Cache::class]))->wrap($app);

@adhocore
Copy link
Owner

Thanks for using it and opening an issue. I will take a close look and get back to you soon.

@adhocore
Copy link
Owner

adhocore commented Aug 29, 2019

have you set up full config as in example?

also can you check if tests/Http/Middleware/ApiAuthTest.php can help you with usge?

@trenggana-klb
Copy link
Author

I already set up full config like yours, the /api/auth endpoint to generate tokens/refresh is working
but the uri in scopes that have to use ApiAuth is always return permission denied even there is a Bearer tokens.

One more thing, what is exactly the values for field scopes in users table?

@adhocore
Copy link
Owner

adhocore commented Aug 30, 2019

scope is the permission or role or both.

for example if you have configured an uri '/some/uri' with 'admin' scope then access to this uri is allowed if and only if the scope value in jwt token contains 'admin'

you can set the scope value somehow for user for which you have to authenticate using jwt.
here is factory implementation: https://github.com/adhocore/phalcon-ext/blob/master/src/Factory/ApiAuthenticator.php

@adhocore
Copy link
Owner

Hello, were you able to use the middleware?

@trenggana-klb
Copy link
Author

trenggana-klb commented Sep 17, 2019

Hi @adhocore, I already try to run in with boilerplate like yours (Phalcon Micro) and everythings work well. Then I have another question, how to implement this (JWT Auth) with my current Phalcon MVC Apps that have Basic Auth, I want to switch it with your jwt-api-auth. My boss tell me to continue (change) what my colleague did. Here is the snippet, he used it as plugin:

<?php
/**
 * Description of SecurityPlugin
 *
 * @path    apps/plugins/SecurityPlugin.php
 *
 */

namespace Somenamespace\Plugin;

use Phalcon\Events\Event;
use Phalcon\Mvc\Dispatcher;

class SecurityPlugin extends BasePlugin
{
    public function beforeExecuteRoute(Event $event, Dispatcher $dispatcher)
    {
        $this->logRequest();

        $username = $this->request->getServer('PHP_AUTH_USER');
        $password = $this->request->getServer('PHP_AUTH_PW');
        $status = true;

        if (empty($username) || empty($password)) {
            $this->setResponseHttpCode(self::HTTP_CODE_400);
            $this->setResponseMessage('Username & Password cannot be empty.');
            $status = false;
        }

        $user = $this->auth($username, $password);

        if (!$user) {
            $this->setResponseHttpCode(self::HTTP_CODE_401);
            $status = false;
        } else {
            if (!$this->developerMode()) {
                $acl = $this->acl($dispatcher, $user->getId());

                if (!$acl) {
                    $this->setResponseHttpCode(self::HTTP_CODE_403);
                    $status = false;
                } else {
                    $this->session->set('auth', $user->toArray());
                    $this->session->set('resource', $acl->toArray());
                }
            }
        }

        if (!$status) {
            $this->generateResponse();

            return false;
        }
    }

    private function auth($username, $password)
    {
        $user = $this->getApiUser($username, $password);

        if (!$user) {
            $this->setResponseMessage('Username & Password is not valid.');

            return false;
        }

        if ($user->getActive() == 0) {
            $this->setResponseMessage('User is not active.');

            return false;
        }

        return $user;
    }

    private function acl($dispatcher, $apiUserId)
    {
        $module = $this->router->getModuleName();
        $controller = $this->router->getControllerName();
        $action = $dispatcher->getParam('action_method');
        $apiResources = $this->getApiResources($module, $controller, $action, $apiUserId);

        if (!$apiResources) {
            $this->setResponseMessage("You don't have permission to access");

            return false;
        }

        return $apiResources;
    }

    private function getApiUser($username, $password)
    {
        $password = md5($password);

        return \Somenamespace\Base\Model\ApiUser::findFirst([
            "username = '$username' AND password = '$password'",
            'cache' => $this->_getCacheKeyModel([
                'apiUser',
                $username,
                $password,
            ]),
        ]);
    }

    private function getApiResources($module, $controller, $action, $apiUserId)
    {
        return \Somenamespace\Base\Model\ApiResource::findFirst([
            "api_user_id = $apiUserId AND module = '$module' AND controller = '$controller' AND action = '$action'",
            'cache' => $this->_getCacheKeyModel([
                'apiResource',
                $module,
                $controller,
                $action,
                $apiUserId,
            ]),
        ]);
    }
}

Any idea? I really appreciate....

@adhocore
Copy link
Owner

adhocore commented Sep 22, 2019

first thing to understand is jwt auth is meant for programmable api consumers and not usual browser requests made by end user. but i think you can still find a way out with some not-so-neat hacks around. (like saving jwt into cookie after successful login, which again not a recommendation from me)

for this reason the current jwt auth support is explicitly supported for micro api auth (edit: should work for mvc as well when used as json api server) and i wanted to have another middleware for mvc in #8 but never finished that (sorry to say that not enough motivation and time for that)

@trenggana-klb
Copy link
Author

Alrite, thank you very much then.....
I really appreciate this package

@adhocore
Copy link
Owner

a new version of this package has been released
https://github.com/adhocore/phalcon-ext/releases/tag/v0.0.9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants