uafrica / oauth-server

OAuth Server
Other
51 stars 51 forks source link

parent_model and parent_id having no effect with Client Credentials flow #27

Closed TsengSR closed 8 years ago

TsengSR commented 8 years ago

I am trying to use the OAuth server with an existing database. I created the databases via migration and login works.

In the oauth_clients table I got my id and client_secret as well as parent_model (set to 'Customers') and parent_id to 1 (which should link to the record with the ID 1 in the Customers table.

However, after logining in via client credentials, it sets owner_model to "client" and owner_id to "22" (which is the first two letters of the client_id => 22b5...).

When trying to authenticate with the token received, it's unable to find a client with the given id and attempts to access the "client" model, which fails as there's no such table, cause in the code below (OAuthAuthenticate class)

public function getUser(Request $request)
{
    try {
        $this->Server->isValidRequest(true, $request->query('access_token'));
        $ownerModel = $this->Server->getAccessToken()->getSession()->getOwnerType();
        $ownerId = $this->Server->getAccessToken()->getSession()->getOwnerId();
        $event = new Event('OAuthServer.getUser', $request, [$ownerModel, $ownerId]);
        EventManager::instance()->dispatch($event);
        if ($event->result) {
            return $event->result;
        } else {
            $model = TableRegistry::get($ownerModel);
            return $model->get($ownerId)->toArray();
        }
    } catch (OAuthException $e) {
        $this->_exception = $e;
        return false;
    }
}

When I manually fix the owner_model to "Customers" and owner_id to 1, it works and I can successfully authenticate against the RestApi. Trying to change

    $result = $query->first();
    if ($result) {
        $client = new ClientEntity($this->server);
        $client->hydrate([
            'id' => $result->id,
            'name' => $result->name,
            'parent_model' => $result->parent_model, // added
            'parent_id' => $result->parent_id // added
        ]);

        return $client;
    }

in ClientStorage class failed of course, since parent_model and parent_id aren't valid properties of the Clients class.

How to get it working?

TsengSR commented 8 years ago

My Workaround so far has been to make my own OAuthAuthenticate class and get the model and id from the oauth_clients tables in case the model is "client" until this issue has been addressed and in the getUser method added this code:

        $this->Server->isValidRequest(true, $request->query('access_token'));
        $ownerModel = $this->Server->getAccessToken()->getSession()->getOwnerType();
        $ownerId = $this->Server->getAccessToken()->getSession()->getOwnerId();

        if($ownerModel=="client") {
            $clientId = $this->Server->getAccessToken()->getSession()->getClient()->getId();

            $modelTable = TableRegistry::get("oauth_clients");
            $client = $modelTable->get($clientId);

            $ownerModel = $client->parent_model;
            $ownerId = $client->parent_id;
        }

But this isn't a very clean solution, but at least allows me to continue work on the project until the bug has been fixed and it may help someone else with the same problem until then.

sean-nicholas commented 8 years ago

Hey, thank you. Had the same problem. Is there any update on this?

dakota commented 8 years ago

I will take a look at this.

A possible work-around for you is to add a listener for the OAuthServer.getUser which receives the model and id and can do the lookup.

dakota commented 8 years ago

This should be fixed now.

The League OAuth2 server automatically sets the owner for the session to be the Client record (In the case of a client crediential grant). The problem here was that the owner_id field was an integer, and so couldn't support the UUID that the client id used.

When doing a Client login now, you should get an instance of the client record. You can easily get the parent by doing:

$client = $this->Auth->user();
$client = new \OAuthServer\Model\Entity\Client($client);
$parent = $client->parent;

Hope this helps!

sean-nicholas commented 8 years ago

Thanks for your quick response. Unfortunately I'm getting still a database error: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'xxx.client' doesn't exist That's because TableRegistry::get($ownerModel) is called with $ownerModel = 'client'. Instead it should be 'OAuthServer.Clients'