package com.vtence.molecule.middlewares; import com.vtence.molecule.Request; import com.vtence.molecule.Response; import com.vtence.molecule.http.Authorization; import com.vtence.molecule.http.BasicCredentials; import com.vtence.molecule.lib.Authenticator; import java.util.Optional; import static com.vtence.molecule.http.HeaderNames.WWW_AUTHENTICATE; import static com.vtence.molecule.http.HttpStatus.BAD_REQUEST; import static com.vtence.molecule.http.HttpStatus.UNAUTHORIZED; import static com.vtence.molecule.http.MimeTypes.TEXT; public class BasicAuthentication extends AbstractMiddleware { private static final String BASIC_AUTHENTICATION = "Basic"; private static final String REMOTE_USER = "REMOTE_USER"; private final String realm; private final Authenticator authenticator; public BasicAuthentication(String realm, Authenticator authenticator) { this.realm = realm; this.authenticator = authenticator; } public void handle(Request request, Response response) throws Exception { Authorization auth = Authorization.of(request); if (auth == null) { unauthorized(response); return; } if (!auth.hasScheme(BASIC_AUTHENTICATION)) { response.status(BAD_REQUEST).done(); return; } BasicCredentials credentials = BasicCredentials.decode(auth.params()); Optional<String> user = authenticator.authenticate(credentials.username(), credentials.password()); if (user.isPresent()) { request.attribute(REMOTE_USER, user.get()); forward(request, response); } else { unauthorized(response); } } private void unauthorized(Response response) { response.status(UNAUTHORIZED) .addHeader(WWW_AUTHENTICATE, challenge()) .contentType(TEXT) .done(); } private String challenge() { return String.format("Basic realm=\"%s\"", realm); } }