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

Client isn't challenged when authentication is set in map but no Authorization header is sent #12

Open
weierophinney opened this issue Dec 31, 2019 · 1 comment

Comments

@weierophinney
Copy link
Contributor

I'm facing the situation, that the API client isn't challenged when authorization is required for a service and no Authorization header is given:

my config:

return array(
    'zf-mvc-auth' => array(
        'authentication' => array(
            'map' => array(
                'MyService\\V1' => 'http_digest',
            ),
            'adapters' => array(
                'http_digest' => array(
                    'adapter' => 'ZF\\MvcAuth\\Authentication\\HttpAdapter',
                    'options' => array(
                        'accept_schemes' => array(
                            0 => 'digest',
                        ),
                        'realm' => 'MDM',
                        'digest_domains' => '/my-service',
                        'nonce_timeout' => '3600',
                        'htdigest' => 'data/users.htdigest',
                    ),
                ),
            ),
        ),
        'authorization' => array(
            'deny_by_default' => false,
        ),
    ),
);

Sending the following request, should challange the client, but the server does not include a WWW-Authenticate header in its response:

> GET /my-service/my-action HTTP/1.1
> Host: localhost
> User-Agent: curl/7.43.0
> Accept: application/json
> 
< HTTP/1.1 403 Forbidden
< Date: Thu, 24 Sep 2015 15:22:55 GMT
< Server: Apache/2.4.16 (Unix) PHP/5.5.23
< X-Powered-By: PHP/5.5.23
< Vary: Accept-Encoding,User-Agent
< Access-Control-Allow-Headers: x-requested-with, Content-Type, origin, authorization, accept, client-security-token
< Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT
< Access-Control-Allow-Origin: *
< Access-Control-Max-Age: 1000
< Content-Length: 119
< Content-Type: application/problem+json

I've identified the following section in ZF\MvcAuth\Authentication\DefaultAuthenticationListener's __invoke function responsible for not challenging the client:

        $type = $this->getTypeFromMap($mvcEvent->getRouteMatch());
        if (false === $type && count($this->adapters) > 1) {
            // Ambiguous situation; no matching type in map, but multiple
            // authentication adapters; return a guest identity.
            $identity = new Identity\GuestIdentity();
            $mvcEvent->setParam('ZF\MvcAuth\Identity', $identity);
            return $identity;
        }

        $type = $type ?: $this->getTypeFromRequest($request);
        if (false === $type) {
            // No authentication type known; trigger any pre-flight actions,
            // and return a guest identity.
            $this->triggerAdapterPreAuth($request, $response);
            $identity = new Identity\GuestIdentity();
            $mvcEvent->setParam('ZF\MvcAuth\Identity', $identity);
            return $identity;
        }

        // Authenticate against first matching adapter
        $identity = $this->authenticate($type, $request, $response, $mvcAuthEvent);

        // If the adapter returns a response instance, return it directly.
        if ($identity instanceof HttpResponse) {
            return $identity;
        }

        // If no identity returned, create a guest identity
        if (! $identity instanceof Identity\IdentityInterface) {
            $identity = new Identity\GuestIdentity();
        }

Changing it like this, the client is at least challenged when no credentials are submitted:

        $type = $this->getTypeFromMap($mvcEvent->getRouteMatch());
        if (false === $type && count($this->adapters) > 1) {
            // Ambiguous situation; no matching type in map, but multiple
            // authentication adapters; return a guest identity.
            $identity = new Identity\GuestIdentity();
            $mvcEvent->setParam('ZF\MvcAuth\Identity', $identity);
            return $identity;
        }

        $typeFromRequest = $this->getTypeFromRequest($request);
        $type = $typeFromRequest ? "{$type}-{$typeFromRequest}" : false;

        if (false === $type) {
            // No authentication type known; trigger any pre-flight actions,
            // and return a guest identity.
            $this->triggerAdapterPreAuth($request, $response);
            $identity = new Identity\GuestIdentity();
            $mvcEvent->setParam('ZF\MvcAuth\Identity', $identity);
            return $identity;
        }

        // Authenticate against first matching adapter
        $identity = $this->authenticate($type, $request, $response, $mvcAuthEvent);

        // If the adapter returns a response instance, return it directly.
        if ($identity instanceof HttpResponse) {
            return $identity;
        }

        // If no identity returned, create a guest identity
        if (! $identity instanceof Identity\IdentityInterface) {
            $identity = new Identity\GuestIdentity();
        }

Originally posted by @VOONWerbeagentur at zfcampus/zf-mvc-auth#101

@weierophinney
Copy link
Contributor Author

The solution offered above indeed triggers the Digest challenge, it is not complete though as the response is not an API problem with status 401, but a successful one with data in the body.


Originally posted by @MassiAtZend at zfcampus/zf-mvc-auth#101 (comment)

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

1 participant