From 074e4bc136e9040352ca15d5f17386d27ad75305 Mon Sep 17 00:00:00 2001 From: Jeidnx Date: Tue, 12 Nov 2024 14:59:22 +0100 Subject: [PATCH] chore: properly implement oidc --- build.gradle | 2 +- config.properties | 14 +- .../java/me/kavin/piped/consts/Constants.java | 8 +- .../me/kavin/piped/server/ServerLauncher.java | 9 +- .../server/handlers/auth/UserHandlers.java | 192 +++++++++++------- .../piped/utils/DatabaseSessionFactory.java | 2 +- .../me/kavin/piped/utils/obj/OidcData.java | 13 +- .../kavin/piped/utils/obj/OidcProvider.java | 29 ++- .../piped/utils/obj/db/OidcUserData.java | 42 +++- .../me/kavin/piped/utils/obj/db/User.java | 2 +- .../changelog/db.changelog-master.xml | 1 + .../changelog/version/2-add-oidc.xml | 21 ++ 12 files changed, 228 insertions(+), 107 deletions(-) create mode 100644 src/main/resources/changelog/version/2-add-oidc.xml diff --git a/build.gradle b/build.gradle index 2fb8183..32b1a00 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ dependencies { implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1' implementation 'com.github.FireMasterK.NewPipeExtractor:NewPipeExtractor:a64e202bb498032e817a702145263590829f3c1d' implementation 'com.github.FireMasterK:nanojson:9f4af3b739cc13f3d0d9d4b758bbe2b2ae7119d7' - implementation 'com.nimbusds:oauth2-oidc-sdk:11.5' + implementation 'com.nimbusds:oauth2-oidc-sdk:11.20.1' implementation 'com.fasterxml.jackson.core:jackson-core:2.17.2' implementation 'com.fasterxml.jackson.core:jackson-annotations:2.17.2' implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.2' diff --git a/config.properties b/config.properties index 2821e3f..cde7ff1 100644 --- a/config.properties +++ b/config.properties @@ -90,10 +90,10 @@ hibernate.connection.password:changeme #frontend.statusPageUrl:https://kavin.rocks #frontend.donationUrl:https://kavin.rocks -# Oidc configuration -#oidc.provider.INSERT_HERE.name:INSERT_HERE -#oidc.provider.INSERT_HERE.clientId:INSERT_HERE -#oidc.provider.INSERT_HERE.clientSecret:INSERT_HERE -#oidc.provider.INSERT_HERE.authUri:INSERT_HERE -#oidc.provider.INSERT_HERE.tokenUri:INSERT_HERE -#oidc.provider.INSERT_HERE.userinfoUri:INSERT_HERE +# SSO via OIDC +# each provider needs to have these three options specified. is the +# friendly name which will be shown to the clients and used in the database. +# If you want to change the name later, you will have to update the database. +# oidc.provider..clientId: +# oidc.provider..clientSecret: +# oidc.provider..issuer: diff --git a/src/main/java/me/kavin/piped/consts/Constants.java b/src/main/java/me/kavin/piped/consts/Constants.java index e4d0920..49128f0 100644 --- a/src/main/java/me/kavin/piped/consts/Constants.java +++ b/src/main/java/me/kavin/piped/consts/Constants.java @@ -196,17 +196,13 @@ public class Constants { } }); oidcProviderConfig.forEach((provider, config) -> { - ObjectNode providerNode = frontendProperties.putObject(provider); OIDC_PROVIDERS.add(new OidcProvider( - getRequiredMapValue(config, "name"), + provider, getRequiredMapValue(config, "clientId"), getRequiredMapValue(config, "clientSecret"), - getRequiredMapValue(config, "authUri"), - getRequiredMapValue(config, "tokenUri"), - getRequiredMapValue(config, "userinfoUri") + getRequiredMapValue(config, "issuer") )); providerNames.add(provider); - config.forEach(providerNode::put); }); frontendProperties.put("imageProxyUrl", IMAGE_PROXY_PART); frontendProperties.putArray("countries").addAll( diff --git a/src/main/java/me/kavin/piped/server/ServerLauncher.java b/src/main/java/me/kavin/piped/server/ServerLauncher.java index 41f015b..f70c979 100644 --- a/src/main/java/me/kavin/piped/server/ServerLauncher.java +++ b/src/main/java/me/kavin/piped/server/ServerLauncher.java @@ -274,7 +274,7 @@ public class ServerLauncher extends MultithreadedHttpServerLauncher { return switch (function) { case "login" -> UserHandlers.oidcLoginResponse(provider, request.getQueryParameter("redirect")); case "callback" -> UserHandlers.oidcCallbackResponse(provider, URI.create(request.getFullUrl())); - case "delete" -> UserHandlers.oidcDeleteResponse(provider, URI.create(request.getFullUrl())); + case "delete" -> UserHandlers.oidcDeleteCallback(provider, URI.create(request.getFullUrl())); default -> HttpResponse.ofCode(500).withHtml("Invalid function `" + function + "`"); }; } catch (Exception e) { @@ -491,6 +491,13 @@ public class ServerLauncher extends MultithreadedHttpServerLauncher { } catch (Exception e) { return getErrorResponse(e, request.getPath()); } + })).map(GET, "/user/delete", AsyncServlet.ofBlocking(executor, request -> { + try { + var session = request.getQueryParameter("session"); + return UserHandlers.oidcDeleteRequest(session); + } catch (Exception e) { + return getErrorResponse(e, request.getPath()); + } })).map(POST, "/logout", AsyncServlet.ofBlocking(executor, request -> { try { return getJsonResponse(UserHandlers.logoutResponse(request.getHeader(AUTHORIZATION)), "private"); diff --git a/src/main/java/me/kavin/piped/server/handlers/auth/UserHandlers.java b/src/main/java/me/kavin/piped/server/handlers/auth/UserHandlers.java index 7fb56ca..3cfe3ee 100644 --- a/src/main/java/me/kavin/piped/server/handlers/auth/UserHandlers.java +++ b/src/main/java/me/kavin/piped/server/handlers/auth/UserHandlers.java @@ -1,12 +1,18 @@ package me.kavin.piped.server.handlers.auth; import com.fasterxml.jackson.core.JsonProcessingException; -import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.proc.BadJOSEException; +import com.nimbusds.jwt.JWT; +import com.nimbusds.jwt.JWTParser; import com.nimbusds.oauth2.sdk.*; import com.nimbusds.oauth2.sdk.auth.ClientAuthentication; import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic; import com.nimbusds.oauth2.sdk.id.State; +import com.nimbusds.oauth2.sdk.pkce.CodeChallengeMethod; +import com.nimbusds.oauth2.sdk.pkce.CodeVerifier; import com.nimbusds.openid.connect.sdk.*; +import com.nimbusds.openid.connect.sdk.claims.IDTokenClaimsSet; import com.nimbusds.openid.connect.sdk.claims.UserInfo; import io.activej.http.HttpResponse; import jakarta.persistence.criteria.CriteriaBuilder; @@ -131,7 +137,8 @@ public class UserHandlers { } URI callback = new URI(Constants.PUBLIC_URL + "/oidc/" + provider.name + "/callback"); - OidcData data = new OidcData(redirectUri); + CodeVerifier codeVerifier = new CodeVerifier(); + OidcData data = new OidcData(redirectUri, codeVerifier); String state = data.getState(); PENDING_OIDC.put(state, data); @@ -139,8 +146,11 @@ public class UserHandlers { AuthenticationRequest oidcRequest = new AuthenticationRequest.Builder( new ResponseType("code"), new Scope("openid"), - provider.clientID, callback).endpointURI(provider.authUri) - .state(new State(state)).nonce(data.nonce).build(); + provider.clientID, callback) + .endpointURI(provider.authUri) + .codeChallenge(codeVerifier, CodeChallengeMethod.S256) + .state(new State(state)) + .nonce(data.nonce).build(); if (redirectUri.equals(Constants.FRONTEND_URL + "/login")) { return HttpResponse.redirect302(oidcRequest.toURI().toString()); @@ -155,11 +165,9 @@ public class UserHandlers { "\">here"); } public static HttpResponse oidcCallbackResponse(OidcProvider provider, URI requestUri) throws Exception { - ClientAuthentication clientAuth = new ClientSecretBasic(provider.clientID, provider.clientSecret); + AuthenticationSuccessResponse authResponse = parseOidcUri(requestUri); - AuthenticationSuccessResponse sr = parseOidcUri(requestUri); - - OidcData data = PENDING_OIDC.get(sr.getState().toString()); + OidcData data = PENDING_OIDC.get(authResponse.getState().toString()); if (data == null) { return HttpResponse.ofCode(400).withHtml( "Your oidc provider sent invalid state data. Try again or contact your oidc admin" @@ -167,12 +175,15 @@ public class UserHandlers { } URI callback = new URI(Constants.PUBLIC_URL + "/oidc/" + provider.name + "/callback"); - AuthorizationCode code = sr.getAuthorizationCode(); - AuthorizationGrant codeGrant = new AuthorizationCodeGrant(code, callback); + AuthorizationCode code = authResponse.getAuthorizationCode(); + AuthorizationGrant codeGrant = new AuthorizationCodeGrant(code, callback, data.pkceVerifier); - TokenRequest tokenReq = new TokenRequest(provider.tokenUri, clientAuth, codeGrant); - OIDCTokenResponse tokenResponse = (OIDCTokenResponse) OIDCTokenResponseParser.parse(tokenReq.toHTTPRequest().send()); + ClientAuthentication clientAuth = new ClientSecretBasic(provider.clientID, provider.clientSecret); + TokenRequest tokenReq = new TokenRequest.Builder(provider.tokenUri, clientAuth, codeGrant).build(); + + com.nimbusds.oauth2.sdk.http.HTTPResponse tokenResponseText = tokenReq.toHTTPRequest().send(); + OIDCTokenResponse tokenResponse = (OIDCTokenResponse) OIDCTokenResponseParser.parse(tokenResponseText); if (!tokenResponse.indicatesSuccess()) { TokenErrorResponse errorResponse = tokenResponse.toErrorResponse(); @@ -181,11 +192,17 @@ public class UserHandlers { OIDCTokenResponse successResponse = tokenResponse.toSuccessResponse(); - if (data.isInvalidNonce((String) successResponse.getOIDCTokens().getIDToken().getJWTClaimsSet().getClaim("nonce"))) { - return HttpResponse.ofCode(400).withHtml( - "Your oidc provider sent an invalid nonce. Try again or contact your oidc admin" - ); - } + JWT idToken = JWTParser.parse(successResponse.getOIDCTokens().getIDTokenString()); + + try { + provider.validator.validate(idToken, data.nonce); + } catch (BadJOSEException e) { + System.out.println("Invalid token received: " + e.toString()); + return HttpResponse.ofCode(400).withHtml("Received a bad token. Please try again"); + } catch (JOSEException e) { + System.out.println("Token processing error" + e.toString()); + return HttpResponse.ofCode(500).withHtml("Internal processing error. Please try again"); + } UserInfoRequest ur = new UserInfoRequest(provider.userinfoUri, successResponse.getOIDCTokens().getBearerAccessToken()); UserInfoResponse userInfoResponse = UserInfoResponse.parse(ur.toHTTPRequest().send()); @@ -200,38 +217,86 @@ public class UserHandlers { UserInfo userInfo = userInfoResponse.toSuccessResponse().getUserInfo(); - - String uid = userInfo.getSubject().toString(); + String sub = userInfo.getSubject().toString(); String sessionId; try (Session s = DatabaseSessionFactory.createSession()) { - // TODO: Add oidc provider to database - String dbName = provider + "-" + uid; CriteriaBuilder cb = s.getCriteriaBuilder(); - CriteriaQuery cr = cb.createQuery(User.class); - Root root = cr.from(User.class); - cr.select(root).where(root.get("username").in( - dbName - )); + CriteriaQuery cr = cb.createQuery(OidcUserData.class); + Root root = cr.from(OidcUserData.class); - User dbuser = s.createQuery(cr).uniqueResult(); + cr.select(root).where(root.get("sub").in(sub)); - if (dbuser == null) { - User newuser = new User(dbName, "", Set.of()); + OidcUserData dbuser = s.createQuery(cr).uniqueResult(); + + if (dbuser != null) { + sessionId = dbuser.getUser().getSessionId(); + } else { + String username = userInfo.getPreferredUsername(); + OidcUserData newUser = new OidcUserData(sub, username, provider.name); var tr = s.beginTransaction(); - s.persist(newuser); + s.persist(newUser); tr.commit(); - - sessionId = newuser.getSessionId(); - } else sessionId = dbuser.getSessionId(); + sessionId = newUser.getUser().getSessionId(); + } } return HttpResponse.redirect302(data.data + "?session=" + sessionId); - } - public static HttpResponse oidcDeleteResponse(OidcProvider provider, URI requestUri) throws Exception { - ClientAuthentication clientAuth = new ClientSecretBasic(provider.clientID, provider.clientSecret); + public static HttpResponse oidcDeleteRequest(String session) throws Exception { + + if (StringUtils.isBlank(session)) { + return HttpResponse.ofCode(400).withHtml("session is a required parameter"); + } + + OidcProvider provider = null; + try (Session s = DatabaseSessionFactory.createSession()) { + + User user = DatabaseHelper.getUserFromSession(session); + + if (user == null) { + return HttpResponse.ofCode(400).withHtml("User not found"); + } + + CriteriaBuilder cb = s.getCriteriaBuilder(); + CriteriaQuery cr = cb.createQuery(OidcUserData.class); + Root root = cr.from(OidcUserData.class); + cr.select(root).where(cb.equal(root.get("user"), user)); + + OidcUserData oidcUserData = s.createQuery(cr).uniqueResult(); + + for (OidcProvider test: Constants.OIDC_PROVIDERS) { + if (test.name.equals(oidcUserData.getProvider())) { + provider = test; + } + } + } + + if (provider == null) { + return HttpResponse.ofCode(400).withHtml("Invalid user"); + } + CodeVerifier pkceVerifier = new CodeVerifier(); + + URI callback = URI.create(String.format("%s/oidc/%s/delete", Constants.PUBLIC_URL, provider.name)); + OidcData data = new OidcData(session + "|" + Instant.now().getEpochSecond(), pkceVerifier); + String state = data.getState(); + PENDING_OIDC.put(state, data); + + AuthenticationRequest oidcRequest = new AuthenticationRequest.Builder( + new ResponseType("code"), + new Scope("openid"), provider.clientID, callback) + .endpointURI(provider.authUri) + .codeChallenge(pkceVerifier, CodeChallengeMethod.S256) + .state(new State(state)) + .nonce(data.nonce) + // This parameter is optional and the idp does't have to honor it. + .maxAge(0) + .build(); + + return HttpResponse.redirect302(oidcRequest.toURI().toString()); + } + public static HttpResponse oidcDeleteCallback(OidcProvider provider, URI requestUri) throws Exception { AuthenticationSuccessResponse sr = parseOidcUri(requestUri); @@ -247,10 +312,11 @@ public class UserHandlers { URI callback = new URI(Constants.PUBLIC_URL + "/oidc/" + provider.name + "/delete"); AuthorizationCode code = sr.getAuthorizationCode(); - AuthorizationGrant codeGrant = new AuthorizationCodeGrant(code, callback); + AuthorizationGrant codeGrant = new AuthorizationCodeGrant(code, callback, data.pkceVerifier); + ClientAuthentication clientAuth = new ClientSecretBasic(provider.clientID, provider.clientSecret); - TokenRequest tokenRequest = new TokenRequest(provider.tokenUri, clientAuth, codeGrant); + TokenRequest tokenRequest = new TokenRequest.Builder(provider.tokenUri, clientAuth, codeGrant).build(); TokenResponse tokenResponse = OIDCTokenResponseParser.parse(tokenRequest.toHTTPRequest().send()); if (!tokenResponse.indicatesSuccess()) { @@ -260,16 +326,25 @@ public class UserHandlers { OIDCTokenResponse successResponse = (OIDCTokenResponse) tokenResponse.toSuccessResponse(); - JWTClaimsSet claims = successResponse.getOIDCTokens().getIDToken().getJWTClaimsSet(); + JWT idToken = JWTParser.parse(successResponse.getOIDCTokens().getIDTokenString()); - if (data.isInvalidNonce((String) claims.getClaim("nonce"))) { - return HttpResponse.ofCode(400).withHtml( - "Your oidc provider sent an invalid nonce. Please try again or contact your oidc admin." - ); + IDTokenClaimsSet claims; + try { + claims = provider.validator.validate(idToken, data.nonce); + } catch (BadJOSEException e) { + System.out.println("Invalid token received: " + e.toString()); + return HttpResponse.ofCode(400).withHtml("Received a bad token. Please try again"); + } catch (JOSEException e) { + System.out.println("Token processing error" + e.toString()); + return HttpResponse.ofCode(500).withHtml("Internal processing error. Please try again"); + } + + Long authTime = (Long) claims.getNumberClaim("auth_time"); + + if (authTime == null) { + return HttpResponse.ofCode(400).withHtml("Couldn't get the `auth_time` claim from the provided id token"); } - long authTime = (long) claims.getClaim("auth_time"); - if (authTime < start) { return HttpResponse.ofCode(500).withHtml( "Your oidc provider didn't verify your identity. Please try again or contact your oidc admin." @@ -277,7 +352,6 @@ public class UserHandlers { } try (Session s = DatabaseSessionFactory.createSession()) { - var tr = s.beginTransaction(); s.remove(DatabaseHelper.getUserFromSession(session)); tr.commit(); @@ -297,31 +371,6 @@ public class UserHandlers { String hash = user.getPassword(); - if (hash.isEmpty()) { - - CriteriaBuilder cb = s.getCriteriaBuilder(); - CriteriaQuery cr = cb.createQuery(OidcUserData.class); - Root root = cr.from(OidcUserData.class); - cr.select(root).where(cb.equal(root.get("user"), user.getId())); - - OidcUserData oidcUserData = s.createQuery(cr).uniqueResult(); - - //TODO: Get user from oidc table and lookup provider - OidcProvider provider = Constants.OIDC_PROVIDERS.get(0); - URI callback = URI.create(String.format("%s/oidc/%s/delete", Constants.PUBLIC_URL, provider.name)); - OidcData data = new OidcData(session + "|" + Instant.now().getEpochSecond()); - String state = data.getState(); - PENDING_OIDC.put(state, data); - - AuthenticationRequest oidcRequest = new AuthenticationRequest.Builder( - new ResponseType("code"), - new Scope("openid"), provider.clientID, callback).endpointURI(provider.authUri) - .state(new State(state)).nonce(data.nonce).maxAge(0).build(); - - - return mapper.writeValueAsBytes(mapper.createObjectNode() - .put("redirect", oidcRequest.toURI().toString())); - } if (!hashMatch(hash, pass)) ExceptionHandler.throwErrorResponse(new IncorrectCredentialsResponse()); @@ -333,7 +382,6 @@ public class UserHandlers { } } - public static byte[] logoutResponse(String session) throws JsonProcessingException { if (StringUtils.isBlank(session)) diff --git a/src/main/java/me/kavin/piped/utils/DatabaseSessionFactory.java b/src/main/java/me/kavin/piped/utils/DatabaseSessionFactory.java index edc6089..9edade8 100644 --- a/src/main/java/me/kavin/piped/utils/DatabaseSessionFactory.java +++ b/src/main/java/me/kavin/piped/utils/DatabaseSessionFactory.java @@ -20,7 +20,7 @@ public class DatabaseSessionFactory { sessionFactory = configuration.addAnnotatedClass(User.class).addAnnotatedClass(Channel.class) .addAnnotatedClass(Video.class).addAnnotatedClass(PubSub.class).addAnnotatedClass(Playlist.class) - .addAnnotatedClass(PlaylistVideo.class).addAnnotatedClass(UnauthenticatedSubscription.class).buildSessionFactory(); + .addAnnotatedClass(PlaylistVideo.class).addAnnotatedClass(UnauthenticatedSubscription.class).addAnnotatedClass(OidcUserData.class).buildSessionFactory(); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/src/main/java/me/kavin/piped/utils/obj/OidcData.java b/src/main/java/me/kavin/piped/utils/obj/OidcData.java index f1bfd6c..6275876 100644 --- a/src/main/java/me/kavin/piped/utils/obj/OidcData.java +++ b/src/main/java/me/kavin/piped/utils/obj/OidcData.java @@ -1,6 +1,8 @@ package me.kavin.piped.utils.obj; +import com.nimbusds.oauth2.sdk.pkce.CodeVerifier; import com.nimbusds.openid.connect.sdk.Nonce; +import com.nimbusds.openid.connect.sdk.validators.IDTokenValidator; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; @@ -9,16 +11,17 @@ import java.util.Base64; public class OidcData { public final Nonce nonce; + public final CodeVerifier pkceVerifier; + public final String data; - public String data; - - public OidcData(String data) { + public OidcData(String data, CodeVerifier pkceVerifier) { this.nonce = new Nonce(); + this.pkceVerifier = pkceVerifier; this.data = data; } - public boolean isInvalidNonce(String nonce) { - return !nonce.equals(this.nonce.toString()); + public boolean validateNonce(String nonce) { + return this.nonce.toString().equals(nonce); } public String getState() { diff --git a/src/main/java/me/kavin/piped/utils/obj/OidcProvider.java b/src/main/java/me/kavin/piped/utils/obj/OidcProvider.java index aedce63..3a1859c 100644 --- a/src/main/java/me/kavin/piped/utils/obj/OidcProvider.java +++ b/src/main/java/me/kavin/piped/utils/obj/OidcProvider.java @@ -2,28 +2,35 @@ package me.kavin.piped.utils.obj; import com.nimbusds.oauth2.sdk.auth.Secret; import com.nimbusds.oauth2.sdk.id.ClientID; +import com.nimbusds.oauth2.sdk.id.Issuer; +import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata; +import com.nimbusds.openid.connect.sdk.validators.IDTokenValidator; import java.net.URI; -import java.net.URISyntaxException; public class OidcProvider { - public String name; - public ClientID clientID; - public Secret clientSecret; + public final String name; + public final ClientID clientID; + public final Secret clientSecret; public URI authUri; public URI tokenUri; public URI userinfoUri; + public IDTokenValidator validator; - public OidcProvider(String name, String clientID, String clientSecret, String authUri, String tokenUri, String userinfoUri) { + public OidcProvider(String name, String clientId, String clientSecret, String issuer){ this.name = name; - this.clientID = new ClientID(clientID); + this.clientID = new ClientID(clientId); this.clientSecret = new Secret(clientSecret); + try { - this.authUri = new URI(authUri); - this.tokenUri = new URI(tokenUri); - this.userinfoUri = new URI(userinfoUri); - } catch (URISyntaxException e) { - System.err.println("Malformed URI for oidc provider '" + name + "' found."); + Issuer iss = new Issuer(issuer); + OIDCProviderMetadata providerData = OIDCProviderMetadata.resolve(iss); + this.authUri = providerData.getAuthorizationEndpointURI(); + this.tokenUri = providerData.getTokenEndpointURI(); + this.userinfoUri = providerData.getUserInfoEndpointURI(); + this.validator = new IDTokenValidator(iss, this.clientID, providerData.getIDTokenJWSAlgs().getFirst(), providerData.getJWKSetURI().toURL()); + } catch (Exception e ) { + System.err.println("Failed to get configuration for '" + name + "': " + e); System.exit(1); } } diff --git a/src/main/java/me/kavin/piped/utils/obj/db/OidcUserData.java b/src/main/java/me/kavin/piped/utils/obj/db/OidcUserData.java index e23d621..748e7d0 100644 --- a/src/main/java/me/kavin/piped/utils/obj/db/OidcUserData.java +++ b/src/main/java/me/kavin/piped/utils/obj/db/OidcUserData.java @@ -1,19 +1,57 @@ package me.kavin.piped.utils.obj.db; +import java.util.Set; + +import org.hibernate.annotations.Cascade; + +import java.io.Serializable; + import jakarta.persistence.*; @Entity @Table(name = "oidc_user_data") -public class OidcUserData { +public class OidcUserData implements Serializable { - @Column(unique = true) + public OidcUserData() { + } + + public OidcUserData(String sub, String username, String provider) { + this.sub = sub; + this.provider = provider; + this.user = new User(username,"", Set.of()); + } + + @Column(name = "sub", unique = true, length = 255) @Id private String sub; @OneToOne + @Cascade(org.hibernate.annotations.CascadeType.ALL) private User user; + @Column(name = "provider", nullable = false) private String provider; + public User getUser() { + return user; + } + public void setUser(User user) { + this.user = user; + } + public String getSub() { + return sub; + } + + public void setSub(String sub) { + this.sub = sub; + } + + public String getProvider() { + return provider; + } + + public void setProvider(String provider) { + this.provider = provider; + } } diff --git a/src/main/java/me/kavin/piped/utils/obj/db/User.java b/src/main/java/me/kavin/piped/utils/obj/db/User.java index 4a3e343..2b8f603 100644 --- a/src/main/java/me/kavin/piped/utils/obj/db/User.java +++ b/src/main/java/me/kavin/piped/utils/obj/db/User.java @@ -21,7 +21,7 @@ public class User implements Serializable { @Column(name = "id") private long id; - @Column(name = "username", unique = true, length = 32) + @Column(name = "username", unique = true, length = 24) private String username; @Column(name = "password", columnDefinition = "text") diff --git a/src/main/resources/changelog/db.changelog-master.xml b/src/main/resources/changelog/db.changelog-master.xml index 4d3a056..4018493 100644 --- a/src/main/resources/changelog/db.changelog-master.xml +++ b/src/main/resources/changelog/db.changelog-master.xml @@ -6,4 +6,5 @@ + diff --git a/src/main/resources/changelog/version/2-add-oidc.xml b/src/main/resources/changelog/version/2-add-oidc.xml new file mode 100644 index 0000000..a968d23 --- /dev/null +++ b/src/main/resources/changelog/version/2-add-oidc.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + +