add redirect to oidc delete; more cleanup

This commit is contained in:
Jeidnx 2024-11-20 16:34:25 +01:00
parent f76f8e0af9
commit e4ba19556c
No known key found for this signature in database
GPG Key ID: 0E9E697B7E99DF39
5 changed files with 69 additions and 12 deletions

View File

@ -9,6 +9,7 @@ import me.kavin.piped.server.ServerLauncher;
import me.kavin.piped.utils.*; import me.kavin.piped.utils.*;
import me.kavin.piped.utils.matrix.SyncRunner; import me.kavin.piped.utils.matrix.SyncRunner;
import me.kavin.piped.utils.obj.MatrixHelper; import me.kavin.piped.utils.obj.MatrixHelper;
import me.kavin.piped.utils.obj.db.OidcData;
import me.kavin.piped.utils.obj.db.PlaylistVideo; import me.kavin.piped.utils.obj.db.PlaylistVideo;
import me.kavin.piped.utils.obj.db.PubSub; import me.kavin.piped.utils.obj.db.PubSub;
import me.kavin.piped.utils.obj.db.Video; import me.kavin.piped.utils.obj.db.Video;
@ -253,5 +254,32 @@ public class Main {
} }
}, 0, TimeUnit.MINUTES.toMillis(60)); }, 0, TimeUnit.MINUTES.toMillis(60));
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) {
var cb = s.getCriteriaBuilder();
var cd = cb.createCriteriaDelete(OidcData.class);
var root = cd.from(OidcData.class);
cd.where(cb.lessThan(root.get("start"), System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(3)));
var tr = s.beginTransaction();
var query = s.createMutationQuery(cd);
int affected = query.executeUpdate();
tr.commit();
if (affected > 0) {
System.out.printf("Cleanup: Removed %o orphaned oidc logins%n", affected);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, 0, TimeUnit.MINUTES.toMillis(5));
} }
} }

View File

@ -490,8 +490,9 @@ public class ServerLauncher extends MultithreadedHttpServerLauncher {
} }
})).map(GET, "/user/delete", AsyncServlet.ofBlocking(executor, request -> { })).map(GET, "/user/delete", AsyncServlet.ofBlocking(executor, request -> {
try { try {
var session = request.getQueryParameter("session"); String session = request.getQueryParameter("session");
return UserHandlers.oidcDeleteRequest(session); String redirect = request.getQueryParameter("redirect");
return UserHandlers.oidcDeleteRequest(session, redirect);
} catch (Exception e) { } catch (Exception e) {
return getErrorResponse(e, request.getPath()); return getErrorResponse(e, request.getPath());
} }

View File

@ -177,6 +177,12 @@ public class UserHandlers {
URI callback = new URI(Constants.PUBLIC_URL + "/oidc/" + provider.name + "/callback"); URI callback = new URI(Constants.PUBLIC_URL + "/oidc/" + provider.name + "/callback");
AuthorizationCode code = authResponse.getAuthorizationCode(); AuthorizationCode code = authResponse.getAuthorizationCode();
if (code == null) {
return HttpResponse.ofCode(400).withHtml(
"Your oidc provider sent an invalid code. Try again or contact your oidc admin"
);
}
AuthorizationGrant codeGrant = new AuthorizationCodeGrant(code, callback, data.getOidVerifier()); AuthorizationGrant codeGrant = new AuthorizationCodeGrant(code, callback, data.getOidVerifier());
ClientAuthentication clientAuth = new ClientSecretBasic(provider.clientID, provider.clientSecret); ClientAuthentication clientAuth = new ClientSecretBasic(provider.clientID, provider.clientSecret);
@ -241,12 +247,16 @@ public class UserHandlers {
return HttpResponse.redirect302(data.data + "?session=" + sessionId); return HttpResponse.redirect302(data.data + "?session=" + sessionId);
} }
public static HttpResponse oidcDeleteRequest(String session) throws Exception { public static HttpResponse oidcDeleteRequest(String session, String redirect) throws Exception {
if (StringUtils.isBlank(session)) { if (StringUtils.isBlank(session)) {
return HttpResponse.ofCode(400).withHtml("session is a required parameter"); return HttpResponse.ofCode(400).withHtml("session is a required parameter");
} }
if (StringUtils.isBlank(redirect)) {
return HttpResponse.ofCode(400).withHtml("redirect is a required parameter");
}
OidcProvider provider = null; OidcProvider provider = null;
try (Session s = DatabaseSessionFactory.createSession()) { try (Session s = DatabaseSessionFactory.createSession()) {
@ -282,7 +292,7 @@ public class UserHandlers {
CodeVerifier pkceVerifier = new CodeVerifier(); CodeVerifier pkceVerifier = new CodeVerifier();
URI callback = URI.create(String.format("%s/oidc/%s/delete", Constants.PUBLIC_URL, provider.name)); URI callback = URI.create(String.format("%s/oidc/%s/delete", Constants.PUBLIC_URL, provider.name));
OidcData data = new OidcData(session + "|" + Instant.now().getEpochSecond(), pkceVerifier); OidcData data = new OidcData(session + "|" + redirect, pkceVerifier);
String state = data.getState(); String state = data.getState();
DatabaseHelper.setOidcData(data); DatabaseHelper.setOidcData(data);
@ -297,7 +307,7 @@ public class UserHandlers {
.nonce(data.getOidNonce()); .nonce(data.getOidNonce());
if (provider.sendMaxAge) { if (provider.sendMaxAge) {
// This parameter is optional and the idp doesn't have to honor it. // This parameter is optional and the idp doesn't have to honor it.
oidcRequestBuilder.maxAge(0); oidcRequestBuilder.maxAge(0);
} }
@ -316,11 +326,18 @@ public class UserHandlers {
); );
} }
long start = Long.parseLong(data.data.split("\\|")[1]); String redirect = data.data.split("\\|")[1];
String session = data.data.split("\\|")[0]; String session = data.data.split("\\|")[0];
URI callback = new URI(Constants.PUBLIC_URL + "/oidc/" + provider.name + "/delete"); URI callback = new URI(Constants.PUBLIC_URL + "/oidc/" + provider.name + "/delete");
AuthorizationCode code = sr.getAuthorizationCode(); AuthorizationCode code = sr.getAuthorizationCode();
if (code == null) {
return HttpResponse.ofCode(400).withHtml(
"Your oidc provider sent an invalid code. Try again or contact your oidc admin"
);
}
AuthorizationGrant codeGrant = new AuthorizationCodeGrant(code, callback, data.getOidVerifier()); AuthorizationGrant codeGrant = new AuthorizationCodeGrant(code, callback, data.getOidVerifier());
ClientAuthentication clientAuth = new ClientSecretBasic(provider.clientID, provider.clientSecret); ClientAuthentication clientAuth = new ClientSecretBasic(provider.clientID, provider.clientSecret);
@ -355,7 +372,7 @@ public class UserHandlers {
return HttpResponse.ofCode(400).withHtml("Couldn't get the `auth_time` claim from the provided id token"); return HttpResponse.ofCode(400).withHtml("Couldn't get the `auth_time` claim from the provided id token");
} }
if (authTime < start) { if (authTime <= data.start) {
return HttpResponse.ofCode(500).withHtml( return HttpResponse.ofCode(500).withHtml(
"Your oidc provider didn't verify your identity. Please try again or contact your oidc admin." "Your oidc provider didn't verify your identity. Please try again or contact your oidc admin."
); );
@ -377,7 +394,7 @@ public class UserHandlers {
tr.commit(); tr.commit();
} }
return HttpResponse.redirect302(Constants.FRONTEND_URL + "/preferences?deleted=" + session); return HttpResponse.redirect302(redirect + "?deleted=true");
} }
public static byte[] deleteUserResponse(String session, String pass) throws IOException { public static byte[] deleteUserResponse(String session, String pass) throws IOException {

View File

@ -247,13 +247,24 @@ public class DatabaseHelper {
} }
public static OidcData getOidcData(String state) { public static OidcData getOidcData(String state) {
try (StatelessSession s = DatabaseSessionFactory.createStatelessSession()) { try (Session s = DatabaseSessionFactory.createSession()) {
CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaBuilder cb = s.getCriteriaBuilder();
CriteriaQuery<OidcData> cr = cb.createQuery(OidcData.class); CriteriaQuery<OidcData> cr = cb.createQuery(OidcData.class);
Root<OidcData> root = cr.from(OidcData.class); Root<OidcData> root = cr.from(OidcData.class);
cr.select(root).where(cb.equal(root.get("state"), state)); cr.select(root).where(cb.equal(root.get("state"), state));
return s.createQuery(cr).uniqueResult(); OidcData data = s.createQuery(cr).uniqueResult();
if (data == null){
return null;
}
var tr = s.beginTransaction();
s.remove(data);
tr.commit();
return data;
} }
} }
} }

View File

@ -27,13 +27,13 @@ public class OidcData implements Serializable {
public String state; public String state;
@Column(name = "start") @Column(name = "start")
public long auth_start; public long start;
public OidcData(String data, CodeVerifier pkceVerifier) { public OidcData(String data, CodeVerifier pkceVerifier) {
this.nonce = new Nonce().toString(); this.nonce = new Nonce().toString();
this.verifierSecret = pkceVerifier.getValue(); this.verifierSecret = pkceVerifier.getValue();
this.data = data; this.data = data;
this.auth_start = System.currentTimeMillis() / 1000L; this.start = System.currentTimeMillis() / 1000L;
this.state = getState(); this.state = getState();
} }