Search code examples
javaauthenticationsecurityjetty

How to prompt User for Basic Auth using Jetty


My aim is to programatically configure a Jetty Server with BASIC authentication. I have managed to get the authentication working when using a REST client like Postman and always sending the authentication header, but I would like the user to be prompted for input using the browaswers native login prompt if they open the page.

The code below is my current status. The response (401) and headers do include "WWW-Authenticate: basic realm="thwCopRealm"", so I do not understand why the user is not being prompted for input.

Can you please help me to configure the server such that the user will be prompted to login using the browsers native login prompt?

Server server = new Server(8080);

HashLoginService loginService = new HashLoginService();
loginService.setName(REALM);
loginService.setConfig(Main.class.getResource("/users.txt").toString());

Constraint constraint = new Constraint(Constraint.__BASIC_AUTH, Roles.USER);
constraint.setAuthenticate(true);

ConstraintMapping constraintMapping = new ConstraintMapping();
constraintMapping.setConstraint(constraint);
constraintMapping.setPathSpec("/*");

ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
securityHandler.setAuthenticator(new BasicAuthenticator());
securityHandler.setRealmName(REALM);
securityHandler.setLoginService(loginService);
securityHandler.addRole(Roles.ADMIN);
securityHandler.addRole(Roles.USER);
securityHandler.addConstraintMapping(constraintMapping);

ExampleServlet copServlet = new ExampleServlet();
ServletHolder copServletHolder = new ServletHolder(copServlet);
    
ServletContextHandler handler = new ServletContextHandler();
handler.addServlet(copServletHolder, "/cop");        
handler.setSecurityHandler(securityHandler);

server.addBean(loginService);
server.setHandler(handler);

Solution

  • And minutes after posting this question I found out that my Domain Admins have disabled Basic authentication prompts on our PCs for security (which makes sense).

    I achieved my goals by modifying two lines: to be Digest instead of Basic.

    Constraint constraint = new Constraint(Constraint.__DIGEST_AUTH, Roles.USER);
    securityHandler.setAuthenticator(new DigestAuthenticator());
    

    The background is that Basic is very insecure in many situations. Its far too easy to lose login data, and any reputable server should be using something more secure.