|
|
@ -15,6 +15,8 @@ import java.util.Optional; |
|
|
|
import org.json.JSONObject; |
|
|
|
import org.json.JSONObject; |
|
|
|
|
|
|
|
|
|
|
|
public class Backend extends PathHandler { |
|
|
|
public class Backend extends PathHandler { |
|
|
|
|
|
|
|
private static final String CLIENT_ID = "client_id"; |
|
|
|
|
|
|
|
private static final String REDIRECT_URI = "redirect_uri"; |
|
|
|
private final SessionService sessions; |
|
|
|
private final SessionService sessions; |
|
|
|
private final UserService users; |
|
|
|
private final UserService users; |
|
|
|
|
|
|
|
|
|
|
@ -23,57 +25,81 @@ public class Backend extends PathHandler { |
|
|
|
users = userService; |
|
|
|
users = userService; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void doLogin(HttpExchange ex) throws IOException { |
|
|
|
private boolean authorize(HttpExchange ex, Session session) throws IOException { |
|
|
|
|
|
|
|
var json = json(ex); |
|
|
|
|
|
|
|
var clientId = json.getString(CLIENT_ID); |
|
|
|
|
|
|
|
var redirect = json.getString(REDIRECT_URI); |
|
|
|
|
|
|
|
System.out.println(json); |
|
|
|
|
|
|
|
return sendEmptyResponse(HTTP_NOT_FOUND,ex); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private boolean doLogin(HttpExchange ex) throws IOException { |
|
|
|
var body = json(ex); |
|
|
|
var body = json(ex); |
|
|
|
|
|
|
|
|
|
|
|
var username = body.has(USERNAME) ? body.getString(USERNAME) : null; |
|
|
|
var username = body.has(USERNAME) ? body.getString(USERNAME) : null; |
|
|
|
var password = body.has(PASSWORD) ? body.getString(PASSWORD) : null; |
|
|
|
var password = body.has(PASSWORD) ? body.getString(PASSWORD) : null; |
|
|
|
|
|
|
|
|
|
|
|
Optional<User> user = users.load(username, password); |
|
|
|
Optional<User> user = users.load(username, password); |
|
|
|
if (user.isPresent()) { |
|
|
|
if (user.isPresent()) return sendUserAndCookie(ex, sessions.createSession(user.get())); |
|
|
|
var session = sessions.createSession(user.get()); |
|
|
|
return sendEmptyResponse(HTTP_UNAUTHORIZED, ex); |
|
|
|
sendUserAndCookie(ex, session); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
sendEmptyResponse(HTTP_UNAUTHORIZED, ex); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void handle(HttpExchange ex) throws IOException { |
|
|
|
public boolean doGet(String path, HttpExchange ex) throws IOException { |
|
|
|
String path = relativePath(ex); |
|
|
|
System.out.printf("GET %s…\n", path); |
|
|
|
String method = ex.getRequestMethod(); |
|
|
|
switch (path) { |
|
|
|
System.out.printf("%s %s…", method, path); |
|
|
|
case "/openid-configuration": |
|
|
|
|
|
|
|
return openidConfig(ex); |
|
|
|
var session = getSession(ex); |
|
|
|
|
|
|
|
if ("login".equals(path) && POST.equals(method)) { |
|
|
|
|
|
|
|
doLogin(ex); // TODO: prevent brute force
|
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
if (session.isEmpty()) { |
|
|
|
return sendEmptyResponse(HTTP_NOT_FOUND, ex); |
|
|
|
sendEmptyResponse(HTTP_UNAUTHORIZED, ex); |
|
|
|
} |
|
|
|
System.err.println("unauthorized"); |
|
|
|
|
|
|
|
return; |
|
|
|
@Override |
|
|
|
|
|
|
|
public boolean doPost(String path, HttpExchange ex) throws IOException { |
|
|
|
|
|
|
|
System.out.printf("POST %s…\n", path); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// pre-login paths
|
|
|
|
|
|
|
|
switch (path) { |
|
|
|
|
|
|
|
case "/login": |
|
|
|
|
|
|
|
return doLogin(ex); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var optSession = getSession(ex); |
|
|
|
|
|
|
|
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// post-login paths
|
|
|
|
|
|
|
|
var session = optSession.get(); |
|
|
|
switch (path) { |
|
|
|
switch (path) { |
|
|
|
case "user": |
|
|
|
case "/authorize": |
|
|
|
sendUserAndCookie(ex, session.get()); |
|
|
|
return authorize(ex,session); |
|
|
|
return; |
|
|
|
case "/user": |
|
|
|
|
|
|
|
return sendUserAndCookie(ex, session); |
|
|
|
} |
|
|
|
} |
|
|
|
System.err.println("not implemented"); |
|
|
|
System.err.println("not implemented"); |
|
|
|
sendEmptyResponse(HTTP_NOT_FOUND, ex); |
|
|
|
return sendEmptyResponse(HTTP_NOT_FOUND, ex); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private Optional<Session> getSession(HttpExchange ex) { |
|
|
|
private Optional<Session> getSession(HttpExchange ex) { |
|
|
|
return SessionToken.from(ex).map(SessionToken::sessionId).flatMap(sessions::retrieve); |
|
|
|
return SessionToken.from(ex).map(SessionToken::sessionId).flatMap(sessions::retrieve); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void sendUserAndCookie(HttpExchange ex, Session session) throws IOException { |
|
|
|
private boolean openidConfig(HttpExchange ex) throws IOException { |
|
|
|
|
|
|
|
var uri = ex.getRequestURI().toString(); |
|
|
|
|
|
|
|
JSONObject json = new JSONObject(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
json.put("authorization_endpoint", prefix(ex) + "/web/authorization.html"); |
|
|
|
|
|
|
|
return sendContent(ex, json); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private boolean sendUserAndCookie(HttpExchange ex, Session session) throws IOException { |
|
|
|
var bytes = new JSONObject(session.user().map(false)).toString().getBytes(UTF_8); |
|
|
|
var bytes = new JSONObject(session.user().map(false)).toString().getBytes(UTF_8); |
|
|
|
var headers = ex.getResponseHeaders(); |
|
|
|
var headers = ex.getResponseHeaders(); |
|
|
|
|
|
|
|
|
|
|
|
headers.add(CONTENT_TYPE, JSON); |
|
|
|
headers.add(CONTENT_TYPE, JSON); |
|
|
|
new SessionToken(session.id()).addTo(headers); |
|
|
|
new SessionToken(session.id()).addTo(headers); |
|
|
|
ex.sendResponseHeaders(200, bytes.length); |
|
|
|
ex.sendResponseHeaders(200, bytes.length); |
|
|
|
ex.getResponseBody().write(bytes); |
|
|
|
var out = ex.getResponseBody(); |
|
|
|
|
|
|
|
out.write(bytes); |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|