From a277be5091ea9cab55deeed1ee9306ecdffa89c7 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Tue, 23 Jul 2024 15:56:16 +0200 Subject: [PATCH] working on authorization flow --- .../java/de/srsoftware/oidc/api/Client.java | 6 +++ .../de/srsoftware/oidc/api/Constants.java | 3 ++ .../de/srsoftware/oidc/api/PathHandler.java | 10 ++++- .../de/srsoftware/oidc/app/Application.java | 4 +- .../de/srsoftware/oidc/backend/Backend.java | 38 ++++++++++++------- .../java/de/srsoftware/oidc/web/Forward.java | 4 +- .../src/main/resources/en/authorization.html | 2 + .../src/main/resources/en/authorization.js | 12 +++++- .../src/main/resources/en/user.js | 2 +- 9 files changed, 58 insertions(+), 23 deletions(-) diff --git a/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Client.java b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Client.java index 2025c5c..d2cc369 100644 --- a/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Client.java +++ b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Client.java @@ -5,9 +5,15 @@ import static de.srsoftware.oidc.api.Constants.*; import java.util.Map; import java.util.Set; +import java.util.UUID; public record Client(String id, String name, String secret, Set redirectUris) { public Map map() { return Map.of(CLIENT_ID, id, NAME, name, SECRET, secret, REDIRECT_URIS, redirectUris); } + + public String generateCode() { + System.err.printf("%s.generateCode() not implemented!", getClass().getSimpleName()); + return UUID.randomUUID().toString(); + } } diff --git a/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Constants.java b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Constants.java index 5577cb7..63ba891 100644 --- a/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Constants.java +++ b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Constants.java @@ -2,9 +2,12 @@ package de.srsoftware.oidc.api; public class Constants { + public + static final String CODE = "code"; public static final String CLIENT_ID = "client_id"; public static final String NAME = "name"; public static final String REDIRECT_URI = "redirect_uri"; public static final String REDIRECT_URIS = "redirect_uris"; public static final String SECRET = "secret"; + public static final String STATE = "state"; } diff --git a/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/PathHandler.java b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/PathHandler.java index 366a992..c3e57a1 100644 --- a/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/PathHandler.java +++ b/de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/PathHandler.java @@ -1,8 +1,7 @@ /* © SRSoftware 2024 */ package de.srsoftware.oidc.api; -import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; -import static java.net.HttpURLConnection.HTTP_OK; +import static java.net.HttpURLConnection.*; import static java.nio.charset.StandardCharsets.UTF_8; import com.sun.net.httpserver.HttpExchange; @@ -11,6 +10,7 @@ import com.sun.net.httpserver.HttpServer; import java.io.IOException; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.stream.Stream; import org.json.JSONObject; @@ -120,6 +120,7 @@ public abstract class PathHandler implements HttpHandler { } public static boolean sendContent(HttpExchange ex, Object o) throws IOException { + if (o instanceof Map map) o = new JSONObject(map); if (o instanceof JSONObject) ex.getResponseHeaders().add(CONTENT_TYPE, JSON); return sendContent(ex, HTTP_OK, o.toString().getBytes(UTF_8)); } @@ -131,4 +132,9 @@ public abstract class PathHandler implements HttpHandler { public static boolean sendError(HttpExchange ex, Object o) throws IOException { return sendContent(ex, HTTP_BAD_REQUEST, o.toString().getBytes(UTF_8)); } + + public static boolean sendRedirect(HttpExchange ex, String url) throws IOException { + ex.getResponseHeaders().add("Location", url); + return sendEmptyResponse(HTTP_MOVED_TEMP, ex); + } } diff --git a/de.srsoftware.oidc.app/src/main/java/de/srsoftware/oidc/app/Application.java b/de.srsoftware.oidc.app/src/main/java/de/srsoftware/oidc/app/Application.java index 4ca596c..cd28cf7 100644 --- a/de.srsoftware.oidc.app/src/main/java/de/srsoftware/oidc/app/Application.java +++ b/de.srsoftware.oidc.app/src/main/java/de/srsoftware/oidc/app/Application.java @@ -49,11 +49,11 @@ public class Application { var tokens = new ArrayList<>(List.of(args)); var map = new HashMap(); while (!tokens.isEmpty()) { - var token = tokens.removeFirst(); + var token = tokens.remove(0); switch (token) { case "--base": if (tokens.isEmpty()) throw new IllegalArgumentException("--path option requires second argument!"); - map.put(BASE_PATH, Path.of(tokens.removeFirst())); + map.put(BASE_PATH, Path.of(tokens.remove(0))); break; default: System.err.printf("Unknown option: %s\n", token); diff --git a/de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/Backend.java b/de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/Backend.java index c9cad79..cd67e44 100644 --- a/de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/Backend.java +++ b/de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/Backend.java @@ -39,11 +39,16 @@ public class Backend extends PathHandler { } private boolean authorize(HttpExchange ex, Session session) throws IOException { - var json = json(ex); - var clientId = json.getString(CLIENT_ID); + var json = json(ex); + var clientId = json.getString(CLIENT_ID); + var optClient = clients.getClient(clientId); + if (optClient.isEmpty()) return sendEmptyResponse(HTTP_NOT_FOUND, ex); + var client = optClient.get(); var redirect = json.getString(REDIRECT_URI); - System.out.println(json); - return sendEmptyResponse(HTTP_NOT_FOUND, ex); + if (!client.redirectUris().contains(redirect)) return sendEmptyResponse(HTTP_BAD_REQUEST, ex); + var state = json.getString(STATE); + var code = client.generateCode(); + return sendContent(ex, Map.of(CODE,code,REDIRECT_URI,redirect,STATE,state)); } private boolean clients(HttpExchange ex, Session session) throws IOException { @@ -117,6 +122,8 @@ public class Backend extends PathHandler { switch (path) { case "/login": return doLogin(ex); + case "/token": + return provideToken(ex); } var optSession = getSession(ex); if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex); @@ -164,17 +171,23 @@ public class Backend extends PathHandler { return sendEmptyResponse(HTTP_OK, ex); } - private boolean openidConfig(HttpExchange ex) throws IOException { - JSONObject json = new JSONObject(); - - json.put("authorization_endpoint", hostname(ex) + "/web/authorization.html"); - return sendContent(ex, json); + private boolean provideToken(HttpExchange ex) throws IOException { + System.err.printf("%s.provideToken(ex) not implemented!\n",getClass().getSimpleName()); + var json = json(ex); + System.err.println(json); + return sendEmptyResponse(HTTP_NOT_FOUND,ex); } + private boolean openidConfig(HttpExchange ex) throws IOException { + return sendContent(ex, Map.of( + "token_endpoint",hostname(ex)+"/api/token", + "authorization_endpoint", hostname(ex) + "/web/authorization.html") + ); + } private boolean sendUserAndCookie(HttpExchange ex, Session session) throws IOException { new SessionToken(session.id()).addTo(ex); - return sendContent(ex, new JSONObject(session.user().map(false))); + return sendContent(ex, session.user().map(false)); } private boolean updatePassword(HttpExchange ex, Session session) throws IOException { @@ -193,7 +206,7 @@ public class Backend extends PathHandler { return sendError(ex, "password mismatch"); } users.updatePassword(user, newPass1); - return sendContent(ex, new JSONObject(user.map(false))); + return sendContent(ex, user.map(false)); } private boolean updateUser(HttpExchange ex, Session session) throws IOException { @@ -206,7 +219,6 @@ public class Backend extends PathHandler { user.username(json.getString(USERNAME)); user.email(json.getString(EMAIL)); users.save(user); - JSONObject response = new JSONObject(user.map(false)); - return sendContent(ex, response); + return sendContent(ex, user.map(false)); } } diff --git a/de.srsoftware.oidc.web/src/main/java/de/srsoftware/oidc/web/Forward.java b/de.srsoftware.oidc.web/src/main/java/de/srsoftware/oidc/web/Forward.java index f9136e3..b2ec48c 100644 --- a/de.srsoftware.oidc.web/src/main/java/de/srsoftware/oidc/web/Forward.java +++ b/de.srsoftware.oidc.web/src/main/java/de/srsoftware/oidc/web/Forward.java @@ -16,8 +16,6 @@ public class Forward extends PathHandler { @Override public boolean doGet(String path, HttpExchange ex) throws IOException { System.out.printf("Forwarding (%d) %s to %s…\n", CODE, path, toPath); - ex.getResponseHeaders().add("Location", toPath); - ex.sendResponseHeaders(CODE, 0); - return true; + return sendRedirect(ex,toPath); } } diff --git a/de.srsoftware.oidc.web/src/main/resources/en/authorization.html b/de.srsoftware.oidc.web/src/main/resources/en/authorization.html index 8b45e68..3e883b8 100644 --- a/de.srsoftware.oidc.web/src/main/resources/en/authorization.html +++ b/de.srsoftware.oidc.web/src/main/resources/en/authorization.html @@ -5,8 +5,10 @@ + +

Authorization!

Not implemented, yet! diff --git a/de.srsoftware.oidc.web/src/main/resources/en/authorization.js b/de.srsoftware.oidc.web/src/main/resources/en/authorization.js index d8d1816..7435f94 100644 --- a/de.srsoftware.oidc.web/src/main/resources/en/authorization.js +++ b/de.srsoftware.oidc.web/src/main/resources/en/authorization.js @@ -1,11 +1,19 @@ var params = new URLSearchParams(window.location.search) var json = Object.fromEntries(params); +async function handleResponse(response){ + if (response.ok){ + var json = await response.json(); + console.log(json); + redirect(json.redirect_uri+'?code='+json.code+'&state='+json.state); + return; + } +} + fetch(api+"/authorize",{ method: 'POST', body: JSON.stringify(json), headers: { 'Content-Type': 'application/json' } -}) - +}).then(handleResponse); \ No newline at end of file diff --git a/de.srsoftware.oidc.web/src/main/resources/en/user.js b/de.srsoftware.oidc.web/src/main/resources/en/user.js index e227ae0..d90e49a 100644 --- a/de.srsoftware.oidc.web/src/main/resources/en/user.js +++ b/de.srsoftware.oidc.web/src/main/resources/en/user.js @@ -1,7 +1,7 @@ var user = null; async function handleUser(response){ if (response.status == UNAUTHORIZED) { - redirect('login.html?return_to='+encodeURI(window.location.href)); + redirect('login.html?return_to='+encodeURIComponent(window.location.href)); return; } if (response.ok){