BTBurke / caddy-jwt

JWT middleware for the Caddy server
MIT License
114 stars 39 forks source link

Error 403 when using filemanager with jwt. #11

Closed targodan closed 7 years ago

targodan commented 8 years ago

Hi there,

I recently tried to setup caddy with filemanager, protected by jwt. However every time I try to edit, delete or upload a file the xhr request fails with a 403 code.

What works

With jwt: Reading files and directories. With basicauth or no auth at all: Everything.

What doesn't work

With jwt: Uploading, editing, renaming and deleting files as well as adding directories.

My setup

Caddy version: Caddy 0.9.1 (+e8e5595 Thu Aug 18 07:29:18 UTC 2016) Caddyfile:

files.MYDOMAIN {
    root /var/www/MYDOMAIN/files
    import config/php7.conf # This includes a fastcgi directive for php7 (this works)
    jwt {
        path /MYNAME
        allow user MYNAME
    }
    filemanager {
        on /MYNAME/
        show /var/www/MYDOMAIN/files/MYNAME
    }
}

Parts of my php script for logging in:

<?php

require 'vendor/autoload.php';
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256;

$jwt_secret = 'I wont show this but it also is exported to the JWT_SECRET environment variable. ;)';
$expiration_time = 3600;

$users = json_decode(file_get_contents('users.json'), true);

$username = array_key_exists('username', $_POST) ? $_POST['username'] : null;
if($username !== null) {
    $user = array_key_exists($username, $users) ? $users[$username] : null;
    $pwd = $_POST['password'];
    if($user !== null && password_verify($pwd, $user['pwd'])) {
        $hmac = new Sha256();
        $token = (new Builder())
                        ->setIssuer('https://files.MYDOMAIN')
                        ->setAudience('https://files.MYDOMAIN')
                        ->setIssuedAt(time())
                        ->setNotBefore(time())
                        ->setExpiration(time() + $expiration_time)
                        ->set('user', $username)
                        ->set('role', $user['role'])
                        ->sign($hmac, $jwt_secret)
                        ->getToken();

        setcookie('jwt_token', $token, time()+$expiration_time, '/', 'files.MYDOMAIN', true);
        header("Location: https://files.MYDOMAIN/".$username);
        $result = "success";
    } else {
        $result = "failure";
    }
} else {
    $result = "";
}

Here is a request for creating a folder called "test" using google chrome:

Request URL:https://files.MYDOMAIN/MYNAME/
Request Method:POST
Status Code:403 
Remote Address:MYIP:443

Response Headers
content-length:14
content-type:text/plain; charset=utf-8
date:Sun, 21 Aug 2016 19:05:46 GMT
server:Caddy
status:403
x-content-type-options:nosniff

Request Headers
:authority:files.MYDOMAIN
:method:POST
:path:/MYNAME/
:scheme:https
accept:*/*
accept-encoding:gzip, deflate, br
accept-language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
cache-control:no-cache
content-length:0
cookie:view-list=false; jwt_token=VALID-JWT-TOKEN
dnt:1
filename:test
origin:https://files.MYDOMAIN
pragma:no-cache
referer:https://files.MYDOMAIN/MYNAME/
token:SOME-TOKEN-FROM-FILEMANAGER
user-agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36

What I tried so far

I opened a post on the caddy forum in case it was just a mistake in my config. There @matt pointed me to the issue hacdias/caddy-filemanager#17 hinting at filemanager providing the css and js files on the fly and not via the filesystem.

I also made a quick site protected by jwt which just sends of an xhr request to see if it is a general problem with jwt and xhr but that worked.

I am happy to supply more information and test things as needed.

BTBurke commented 8 years ago

Thanks for the detailed bug report. The JWT middleware only ever responds with 401 on auth failures so the 403 must be coming from file manager.

There are only a few reasons why this might be the case. One could be that JWT is clobbering headers required by FileManager. JWT sets a 'token' header as it proxies the request, so that could be silently overwritten if FM is using the same header.

I'll take a look at the FM code this weekend to see if that is the problem.

On Aug 23, 2016, at 6:42 PM, Luca Corbatto notifications@github.com wrote:

Hi there,

I recently tried to setup caddy with filemanager, protected by jwt. However every time I try to edit, delete or upload a file the xhr request fails with a 403 code.

What works

With jwt: Reading files and directories. With basicauth or no auth at all: Everything.

What doesn't work

With jwt: Uploading, editing, renaming and deleting files as well as adding directories.

My setup

Caddy version: Caddy 0.9.1 (+e8e5595 Thu Aug 18 07:29:18 UTC 2016) Caddyfile:

files.MYDOMAIN { root /var/www/MYDOMAIN/files import config/php7.conf # This includes a fastcgi directive for php7 (this works) jwt { path /MYNAME allow user MYNAME } filemanager { on /MYNAME/ show /var/www/MYDOMAIN/files/MYNAME } } Parts of my php script for logging in:

<?php

require 'vendor/autoload.php'; use Lcobucci\JWT\Builder; use Lcobucci\JWT\Signer\Hmac\Sha256;

$jwt_secret = 'I wont show this but it also is exported to the JWT_SECRET environment variable. ;)'; $expiration_time = 3600;

$users = json_decode(file_get_contents('users.json'), true);

$username = array_key_exists('username', $_POST) ? $_POST['username'] : null; if($username !== null) { $user = array_key_exists($username, $users) ? $users[$username] : null; $pwd = $_POST['password']; if($user !== null && password_verify($pwd, $user['pwd'])) { $hmac = new Sha256(); $token = (new Builder()) ->setIssuer('https://files.MYDOMAIN') ->setAudience('https://files.MYDOMAIN') ->setIssuedAt(time()) ->setNotBefore(time()) ->setExpiration(time() + $expiration_time) ->set('user', $username) ->set('role', $user['role']) ->sign($hmac, $jwt_secret) ->getToken();

    setcookie('jwt_token', $token, time()+$expiration_time, '/', 'files.MYDOMAIN', true);
    header("Location: https://files.MYDOMAIN/".$username);
    $result = "success";
} else {
    $result = "failure";
}

} else { $result = ""; } Here is a request for creating a folder called "test" using google chrome:

Request URL:https://files.MYDOMAIN/MYNAME/ Request Method:POST Status Code:403 Remote Address:MYIP:443

Response Headers content-length:14 content-type:text/plain; charset=utf-8 date:Sun, 21 Aug 2016 19:05:46 GMT server:Caddy status:403 x-content-type-options:nosniff

Request Headers :authority:files.MYDOMAIN :method:POST :path:/MYNAME/ :scheme:https accept:/ accept-encoding:gzip, deflate, br accept-language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4 cache-control:no-cache content-length:0 cookie:view-list=false; jwt_token=VALID-JWT-TOKEN dnt:1 filename:test origin:https://files.MYDOMAIN pragma:no-cache referer:https://files.MYDOMAIN/MYNAME/ token:SOME-TOKEN-FROM-FILEMANAGER user-agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 What I tried so far

I opened a post on the caddy forum in case it was just a mistake in my config. There @matt pointed me to the issue hacdias/caddy-filemanager#17 hinting at filemanager providing the css and js files on the fly and not via the filesystem.

I also made a quick site protected by jwt which just sends of an xhr request to see if it is a general problem with jwt and xhr but that worked.

I am happy to supply more information and test things as needed.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

targodan commented 8 years ago

Thanks for the quick answer. The clobbering of headers sounds promising since this is part of the request:

Request Headers
...
token:SOME-TOKEN-PROPABLY-FROM-FILEMANAGER
...
BTBurke commented 8 years ago

@targodan Give it a shot now by building caddy again with the JWT plugin from the website. I removed the token header because I don't think a lot of people have a need to access the full encoded token.

targodan commented 8 years ago

@BTBurke When I download the version with all packages it does not rebuild and still gives me version Caddy 0.9.1 (+e8e5595 Thu Aug 18 07:29:18 UTC 2016). However when I unchecked the prometheus plugin it did rebuild (version Caddy 0.9.1 (+e8e5595 Tue Aug 23 19:48:26 UTC 2016)) it still doesn't work though. Same result. Is that maybe not the latest version?

Oh and I just noticed loading https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.3/mode-txt.js fails with 404 but I guess thats a problem in the filemanager.

BTBurke commented 8 years ago

The version with all the packages is likely pre-built. Try downloading a custom one with just the plugins you are using. That should pull in the latest changes.

On Aug 24, 2016, at 3:59 AM, Luca Corbatto notifications@github.com wrote:

@BTBurke When I download the version with all packages it does not rebuild and still gives me version Caddy 0.9.1 (+e8e5595 Thu Aug 18 07:29:18 UTC 2016). However when I unchecked the prometheus plugin it did rebuild (version Caddy 0.9.1 (+e8e5595 Tue Aug 23 19:48:26 UTC 2016)) it still doesn't work though. Same result. Is that maybe not the latest version?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

targodan commented 8 years ago

Tried that again this morning and just like yesterday I managed to get the new version Caddy 0.9.1 (+e8e5595 Wed Aug 24 06:56:35 UTC 2016) but still the same problem.

targodan commented 8 years ago

Ok, just managed to build caddy myself with filemanager and jwt and it worked. I guess the version on caddyserver.com is not up to date.

targodan commented 7 years ago

I just downloaded the new version of caddy (0.9.3) and I still get the same errors.

I don't know how the release/update process of caddy and its plugins works but it seems like this fix hasent made it to the official release.

BTBurke commented 7 years ago

I don't get involved in the caddy builds. You should probably open an issue there because this has more to do with the Caddy build server than my library.

I assume it still works when you build a custom binary? If that's the case, I'm going to close this issue.