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

Server usage #4

Open
CMCDragonkai opened this issue Oct 8, 2013 · 8 comments
Open

Server usage #4

CMCDragonkai opened this issue Oct 8, 2013 · 8 comments

Comments

@CMCDragonkai
Copy link

From the server side, it seems that not only are we authenticating the user's credentials, but also authenticating against their request parameters.

For example, on the server usage it you're asking for 'POST' method, domain, api path, content-type, and even a specific post payload.

I'm guessing this is part of the Hawk protocol.

But doesn't this mean, that we have to manually write what kind of request the user is going to send, for every possible API end point? Can those extra request parameters be optional?

@davedevelopment
Copy link
Contributor

The user signs the request, based on the information it is sending, the server only confirms that the signature matches the information it received. I think.

@simensen
Copy link
Member

simensen commented Oct 8, 2013

@CMCDragonkai What @davedevelopment said is more or less true. The idea behind Hawk is that as a client you are signing an individual request and the server can verify that the signature matches for the request it is answering.

For example, say you intercept a client request for "GET /". If you then change this to "DELETE /allUsers", you would not want to honor that request.

This does not, however, mean that you need to perform these operations at each endpoint individually. Everything you need to perform these operations should be available to you at a global/request level. For example, the Hawk Stack Middleware is able to protect any incoming request generically. See this code for what this looks like:

https://github.com/dflydev/dflydev-stack-hawk/blob/master/src/Dflydev/Stack/Hawk.php#L45-L88

The meat is here:

<?php
// Get the authorization header
$header = HeaderFactory::createFromString(
    'Authorization',
    $request->headers->get('authorization')
);

// Payload validation is optional
$payload = $shouldValidatePayloadRequest
    ? ($request->getMethod() !== 'GET' ? $request->getContent() : null)
    : null;

// Ask the server to authenticate
$authenticationResponse = $server->authenticate(
    $request->getMethod(),
    $request->getHost(),
    $request->getPort(),
    $request->getRequestUri(),
    $request->headers->get('content-type'),
    $payload,
    $header
);

None of the code above is endpoint specific. It can be added to something like a before middleware or some other login check/authentication/authorization block in your application's lifecycle.

This example uses Symfony's HTTP Request object. Depending on your framework of choice you should hopefully have something similar to work with. It is possible to do this with raw PHP, though, and does not require a framework. It might just be a little more painful. :)

And yes, some things may be optional. Payload validation is because that can be tricky/resource intensive.

Does this answer your question?

@CMCDragonkai
Copy link
Author

Thanks, I'm working on it right now. But just a quick question, what is this:

$credentialsProvider = function ($id) {
    if ('12345' === $id) {
        return new Dflydev\Hawk\Credentials\Credentials(
            'afe89a3x',  // shared key
            'sha256',    // default: sha256
            '12345'      // identifier, default: null
        );
    }
};

Why would the server builder require a credentials provider? What does all those values mean? Are those the credentials of the server? Therefore are the used in the creation of credentials for the client? Why does the server need credentials?

Also it appears the server authorization header uses the same credentials that came in from the client.

Also after we validate the request parameters. We can get the credentials from $response->credentials(). Does that return the id and the secret? Because I would need to check against the database to see if the id and the secret is correct.

@CMCDragonkai
Copy link
Author

Oh I understand what the credentials provider is. It basically creates the credential object based on the client's Id.

However now if the ID didn't exist in the database, do I return null? Return false? What do I return?

@simensen
Copy link
Member

I suppose this could be better documented. The examples sort of imply that you only have to return if you return a credentials object. Simply don't return a credentials object if the request is not authenticated.

@CMCDragonkai
Copy link
Author

I see, I was returning a Credentials object with a false empty secret. This seems to create an hmac with false as the secret which I think seems to work. And this value can still be compared with the values that are being passed in.

@simensen
Copy link
Member

hm. i'm not really in a place to double check this right now but i took a real quick look at the code and realize i could actually be wrong. :) i think that if you return null bad things might happen. let me know what you experience...

it is possible that we should maybe be throwing an UnauthorizedException if credentials are null. here:

https://github.com/dflydev/dflydev-hawk/blob/master/src/Dflydev/Hawk/Server/Server.php#L106

@CMCDragonkai
Copy link
Author

That's what I was worried about. Lol.

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

3 participants