diff --git a/http.c b/http.c index 67c9c6fc60..82f2562f30 100644 --- a/http.c +++ b/http.c @@ -2354,7 +2354,21 @@ static int http_request_recoverable(const char *url, if (options->effective_url && options->base_url) { if (update_url_from_redirect(options->base_url, url, options->effective_url)) { + struct strvec wwwauth_headers = STRVEC_INIT; + + /* + * Preserve wwwauth_headers across the call to + * credential_from_url(): if the effective URL doesn't + * specify its own credentials, a credential helper + * might need the wwwauth[] array from the server's + * redirect response in order to authenticate. + */ + strvec_pushv(&wwwauth_headers, + http_auth.wwwauth_headers.v); credential_from_url(&http_auth, options->base_url->buf); + strvec_pushv(&http_auth.wwwauth_headers, + wwwauth_headers.v); + strvec_clear(&wwwauth_headers); url = options->effective_url->buf; } } diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 40a690b0bb..664f23fc6c 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -202,6 +202,7 @@ RewriteRule ^/dumb-redir/(.*)$ /dumb/$1 [R=301] RewriteRule ^/smart-redir-perm/(.*)$ /smart/$1 [R=301] RewriteRule ^/smart-redir-temp/(.*)$ /smart/$1 [R=302] RewriteRule ^/smart-redir-auth/(.*)$ /auth/smart/$1 [R=301] +RewriteRule ^/custom_auth_redir/(.*)$ /custom_auth/$1 [R=302] RewriteRule ^/smart-redir-limited/(.*)/info/refs$ /smart/$1/info/refs [R=301] RewriteRule ^/ftp-redir/(.*)$ ftp://localhost:1000/$1 [R=302] diff --git a/t/t5563-simple-http-auth.sh b/t/t5563-simple-http-auth.sh index 0063581615..04c8b15324 100755 --- a/t/t5563-simple-http-auth.sh +++ b/t/t5563-simple-http-auth.sh @@ -557,6 +557,51 @@ test_expect_success 'access using bearer auth' ' EOF ' +test_expect_success 'bearer auth after redirect preserves wwwauth headers' ' + test_when_finished "per_test_cleanup" && + + set_credential_reply get <<-EOF && + capability[]=authtype + authtype=Bearer + credential=YS1naXQtdG9rZW4= + EOF + + cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && + id=1 creds=Bearer YS1naXQtdG9rZW4= + EOF + + cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && + id=1 status=200 + id=default response=WWW-Authenticate: FooBar param1="value1" param2="value2" + id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0 + id=default response=WWW-Authenticate: Basic realm="example.com" + EOF + + test_config_global credential.helper test-helper && + test_config_global credential.useHttpPath true && + git ls-remote "$HTTPD_URL/custom_auth_redir/repo.git" && + + expect_credential_query get <<-EOF && + capability[]=authtype + capability[]=state + protocol=http + host=$HTTPD_DEST + path=custom_auth/repo.git + wwwauth[]=FooBar param1="value1" param2="value2" + wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0 + wwwauth[]=Basic realm="example.com" + EOF + + expect_credential_query store <<-EOF + capability[]=authtype + authtype=Bearer + credential=YS1naXQtdG9rZW4= + protocol=http + host=$HTTPD_DEST + path=custom_auth/repo.git + EOF +' + test_expect_success 'access using bearer auth with invalid credentials' ' test_when_finished "per_test_cleanup" &&