package jenkins.security;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequest;
import hudson.model.UnprotectedRootAction;
import hudson.model.User;
import hudson.util.HttpResponses;
import hudson.util.Scrambler;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.JenkinsRule.WebClient;
import org.jvnet.hudson.test.TestExtension;
import org.kohsuke.stapler.HttpResponse;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.net.URL;
/**
* @author Kohsuke Kawaguchi
*/
public class BasicHeaderProcessorTest {
@Rule
public JenkinsRule j = new JenkinsRule();
private WebClient wc;
/**
* Tests various ways to send the Basic auth.
*/
@Test
public void testVariousWaysToCall() throws Exception {
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
User foo = User.get("foo");
User bar = User.get("bar");
wc = j.createWebClient();
// call without authentication
makeRequestWithAuthAndVerify(null, "anonymous");
// call with API token
ApiTokenProperty t = foo.getProperty(ApiTokenProperty.class);
final String token = t.getApiToken();
makeRequestWithAuthAndVerify("foo:"+token, "foo");
// call with invalid API token
makeRequestAndFail("foo:abcd"+token);
// call with password
makeRequestWithAuthAndVerify("foo:foo", "foo");
// call with incorrect password
makeRequestAndFail("foo:bar");
wc.login("bar");
// if the session cookie is valid, then basic header won't be needed
makeRequestWithAuthAndVerify(null, "bar");
// if the session cookie is valid, and basic header is set anyway login should not fail either
makeRequestWithAuthAndVerify("bar:bar", "bar");
// but if the password is incorrect, it should fail, instead of silently logging in as the user indicated by session
makeRequestAndFail("foo:bar");
}
private void makeRequestAndFail(String userAndPass) throws IOException, SAXException {
try {
makeRequestWithAuthAndVerify(userAndPass, "-");
fail();
} catch (FailingHttpStatusCodeException e) {
assertEquals(401, e.getStatusCode());
}
}
private void makeRequestWithAuthAndVerify(String userAndPass, String username) throws IOException, SAXException {
WebRequest req = new WebRequest(new URL(j.getURL(),"test"));
req.setEncodingType(null);
if (userAndPass!=null)
req.setAdditionalHeader("Authorization","Basic "+Scrambler.scramble(userAndPass));
Page p = wc.getPage(req);
assertEquals(username, p.getWebResponse().getContentAsString().trim());
}
@TestExtension
public static class WhoAmI implements UnprotectedRootAction {
@Override
public String getIconFileName() {
return null;
}
@Override
public String getDisplayName() {
return null;
}
@Override
public String getUrlName() {
return "test";
}
public HttpResponse doIndex() {
User u = User.current();
return HttpResponses.plainText(u!=null ? u.getId() : "anonymous");
}
}
}