Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add authentication to login fakesmtp page #60

Open
ilkin opened this issue Jun 2, 2022 · 9 comments
Open

Add authentication to login fakesmtp page #60

ilkin opened this issue Jun 2, 2022 · 9 comments
Labels

Comments

@ilkin
Copy link

ilkin commented Jun 2, 2022

Please add login page to authenticate fakesmtp interface. Authentication could be optional and Username and password can canfigure in application.properties.

@gessnerfl
Copy link
Owner

Will consider it in a future release. Contribution would also be appreciated ;)

@grig0ry
Copy link

grig0ry commented Sep 9, 2022

+1, this would be useful

@gessnerfl
Copy link
Owner

@ilkin @grig0ry
Do have any specific authentication method in mind? LDAP, OAuth, SAML2, etc.

@smuda
Copy link
Contributor

smuda commented Sep 10, 2022

Please make this optional. Our use case would be crippled with forced authentication.

@gessnerfl
Copy link
Owner

@smuda yes in case this is getting implemented authentication will be optional.

@ilkin / @grig0ry can you please elaborate in more detail the need for authentication? The tool is intended for development purposes only.

@grig0ry
Copy link

grig0ry commented Sep 11, 2022

@gessnerfl In our case, we run test builds of the application publicly, for QA and the development team. With a secure web UI, it would be calmer :)

@ilkin
Copy link
Author

ilkin commented Feb 3, 2023

Also, we are using it for QA and UAT purposes and it is a public server in the company that many users can access, so simple authentication might be good at least.

@Slartibartfast27
Copy link

Slartibartfast27 commented Jun 2, 2023

Just a thought: We also use fakesmtp, which contains non-public data in testcases. Therefore we added traefik as a reverse proxy with basic authentication before and made fakesmtp website accessible only through traefik, see https://doc.traefik.io/traefik/middlewares/http/basicauth/
Maybe this could be a simple solution without the need to change a line in fakesmtp.

This is our docker-compose file (no exposed ports for web interface):

version: '3'
services:
  k-fakesmtp:
    # https://hub.docker.com/r/gessnerfl/fake-smtp-server
    # https://github.com/gessnerfl/fake-smtp-server
    image:          gessnerfl/fake-smtp-server
    container_name: k-fakesmtp
    environment:
      - TZ=Europe/Zurich
    volumes:
      - ./mountpoints/application.properties:/root/application.properties:ro
    entrypoint: ["java",
                 "-Djava.security.egd=file:/dev/./urandom",
                 "-Dfile.encoding=utf-8",
                 "-cp", "@/app/jib-classpath-file",
                 "de.gessnerfl.fakesmtp.Application",
                 "--spring.config.location=/root/application.properties"]
    labels:
      - traefik.enable=true

      - traefik.http.routers.fakesmtpHTTPS.rule=Host(`fakesmtp-dev01.company.com`)
      - traefik.http.routers.fakesmtpHTTPS.tls=true
      - traefik.http.routers.fakesmtpHTTPS.middlewares=basicAuthForUsers@file

      - traefik.http.services.fakesmtp.loadbalancer.server.port=5080

    networks:
      - traefik_shared
    ports:
      - 5025:5025
      # do NOT expose ports 5080 / 5081 as we want to have basicAuth from traefik

networks:
  traefik_shared:
    external:
      name: traefik_shared

@jessec
Copy link

jessec commented Jun 2, 2023

Not sure if it is useful for anybody but you can implement a quick and dirty, but easy solution with this class. You could redirect to a login page if the right cookie is not found to set the right cookie.

package proxy;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.URL;
import java.util.List;
import java.util.Map;

public class ReverseProxyServer {

private static final int PORT = 8000;
private static final String DESTINATION_URL = "http://localhost:8080";

public static void main(String[] args) throws IOException {
    HttpServer server = HttpServer.create(new InetSocketAddress(PORT), 0);
    server.createContext("/", new RequestHandler());
    server.start();
    System.out.println("Reverse Proxy Server started on port " + PORT);
}

static class RequestHandler implements HttpHandler {
    @Override
    public void handle(HttpExchange exchange) throws IOException {
        String requestMethod = exchange.getRequestMethod();
        String requestPath = exchange.getRequestURI().getPath();
        
        String requestQuery = exchange.getRequestURI().getQuery();
        
        
        System.out.println(requestQuery);
        
        String destinationUrl = DESTINATION_URL + requestPath + "?" + requestQuery;

        HttpURLConnection connection = (HttpURLConnection) new URL(destinationUrl).openConnection();
        connection.setRequestMethod(requestMethod);

        // Forward headers from the original request to the destination
        for (String header : exchange.getRequestHeaders().keySet()) {
            connection.setRequestProperty(header, exchange.getRequestHeaders().getFirst(header));
        }

        // Copy the cookies from the original request to the destination
        Map<String, List<String>> cookieHeaders = exchange.getRequestHeaders();
        if (cookieHeaders.containsKey("Cookie")) {
            String cookies = String.join("; ", cookieHeaders.get("Cookie"));
            System.out.println(cookies);
            connection.setRequestProperty("Cookie", cookies);
        }
        
        // Copy the response from the destination to the client
        try (OutputStream outputStream = exchange.getResponseBody();
             InputStream inputStream = connection.getInputStream()) {
            exchange.sendResponseHeaders(connection.getResponseCode(), 0);
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        } finally {
            connection.disconnect();
        }
    }
}

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants