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

Implement oidc #628

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
604fa65
Implement oidc
Jeidnx Jun 18, 2023
375ee58
Better Error handling for oidc config
Jeidnx Jun 19, 2023
143711c
Save redirect in state
Jeidnx Jun 19, 2023
18d9317
Show warning message before oidc login
Jeidnx Jun 19, 2023
f4b9dff
Only show warning when not redirecting to configured frontend
Jeidnx Jun 27, 2023
53d9b9d
Merge branch 'master' into oidc
Jeidnx Jul 4, 2023
97889f3
Merge remote-tracking branch 'origin/master' into oidc
FireMasterK Aug 5, 2023
847f80c
Simplify config handling.
FireMasterK Aug 5, 2023
946ac45
Add missing newline.
FireMasterK Aug 5, 2023
0eb2351
Format all code.
FireMasterK Aug 5, 2023
9b7246a
Merge branch 'master' into oidc
Jeidnx Oct 24, 2023
e7f2187
Implement account deletion and cleanup some code
Jeidnx Oct 25, 2023
c1fde37
Refactor oidc logic into UserHandlers
Jeidnx Oct 26, 2023
024435f
Add database migration for username length change.
FireMasterK Oct 26, 2023
470efd8
Revert "Add database migration for username length change."
Jeidnx Oct 29, 2023
5f6a83a
Add code from the meeting.
FireMasterK Oct 29, 2023
868103c
Merge branch 'master' into oidc
Jeidnx Nov 6, 2024
074e4bc
chore: properly implement oidc
Jeidnx Nov 12, 2024
580eb7f
Simplify oidc hash generation.
FireMasterK Nov 17, 2024
9520a3c
Simplify error handling code a little.
FireMasterK Nov 17, 2024
b0725f8
Remove debug code and format.
FireMasterK Nov 17, 2024
74a6751
Move OidcData to db + some cleanup
Jeidnx Nov 20, 2024
f76f8e0
randomize username
Jeidnx Nov 20, 2024
e4ba195
add redirect to oidc delete; more cleanup
Jeidnx Nov 20, 2024
77cd736
explicitly reject empty hashes
Jeidnx Nov 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Remove debug code and format.
  • Loading branch information
FireMasterK committed Nov 17, 2024
commit b0725f882a2bc02695bc885b250b7d3a08549aa5
112 changes: 61 additions & 51 deletions src/main/java/me/kavin/piped/server/handlers/auth/UserHandlers.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public static byte[] loginResponse(String user, String pass)
}
}

public static HttpResponse oidcLoginResponse(OidcProvider provider, String redirectUri) throws Exception{
public static HttpResponse oidcLoginResponse(OidcProvider provider, String redirectUri) throws Exception {
if (StringUtils.isBlank(redirectUri)) {
return HttpResponse.ofCode(400).withHtml("redirect is a required parameter");
}
Expand All @@ -146,9 +146,10 @@ public static HttpResponse oidcLoginResponse(OidcProvider provider, String redir
AuthenticationRequest oidcRequest = new AuthenticationRequest.Builder(
new ResponseType("code"),
new Scope("openid"),
provider.clientID, callback)
.endpointURI(provider.authUri)
.codeChallenge(codeVerifier, CodeChallengeMethod.S256)
provider.clientID, callback
)
.endpointURI(provider.authUri)
.codeChallenge(codeVerifier, CodeChallengeMethod.S256)
.state(new State(state))
.nonce(data.nonce).build();

Expand All @@ -164,6 +165,7 @@ public static HttpResponse oidcLoginResponse(OidcProvider provider, String redir
oidcRequest.toURI().toString() +
"\">here</a></body></html>");
}

public static HttpResponse oidcCallbackResponse(OidcProvider provider, URI requestUri) throws Exception {
AuthenticationSuccessResponse authResponse = parseOidcUri(requestUri);

Expand Down Expand Up @@ -196,20 +198,18 @@ public static HttpResponse oidcCallbackResponse(OidcProvider provider, URI reque

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");
}
} catch (BadJOSEException e) {
System.err.println("Invalid token received: " + e);
return HttpResponse.ofCode(400).withHtml("Received a bad token. Please try again");
} catch (JOSEException e) {
System.err.println("Token processing error: " + e);
return HttpResponse.ofCode(500).withHtml("Internal processing error. Please try again");
Comment on lines +210 to +213
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

withPlainText

}

UserInfoRequest ur = new UserInfoRequest(provider.userinfoUri, successResponse.getOIDCTokens().getBearerAccessToken());
UserInfoResponse userInfoResponse = UserInfoResponse.parse(ur.toHTTPRequest().send());

if (!userInfoResponse.indicatesSuccess()) {
System.out.println(userInfoResponse.toErrorResponse().getErrorObject().getCode());
System.out.println(userInfoResponse.toErrorResponse().getErrorObject().getDescription());
return HttpResponse.ofCode(500).withHtml(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

withPlainText

"The userinfo endpoint returned an error. Please try again or contact your oidc admin\n\n" +
userInfoResponse.toErrorResponse().getErrorObject().getDescription());
Expand Down Expand Up @@ -245,19 +245,19 @@ public static HttpResponse oidcCallbackResponse(OidcProvider provider, URI reque
}

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);
try (Session s = DatabaseSessionFactory.createSession()) {
User user = DatabaseHelper.getUserFromSession(session);

if (user == null) {
return HttpResponse.ofCode(400).withHtml("User not found");
}
if (user == null) {
return HttpResponse.ofCode(400).withHtml("User not found");
}

CriteriaBuilder cb = s.getCriteriaBuilder();
CriteriaQuery<OidcUserData> cr = cb.createQuery(OidcUserData.class);
Expand All @@ -266,41 +266,50 @@ public static HttpResponse oidcDeleteRequest(String session) throws Exception {

OidcUserData oidcUserData = s.createQuery(cr).uniqueResult();

for (OidcProvider test: Constants.OIDC_PROVIDERS) {
if (test.name.equals(oidcUserData.getProvider())) {
provider = test;
}
if (oidcUserData == null) {
return HttpResponse.ofCode(400).withHtml("User doesn't have an oidc account");
}

for (OidcProvider oidcProvider : Constants.OIDC_PROVIDERS) {
if (oidcProvider.name.equals(oidcUserData.getProvider())) {
provider = oidcProvider;
break;
}
}
}
}

if (provider == null) {
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();
}

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 doesn'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);

OidcData data = UserHandlers.PENDING_OIDC.get(sr.getState().toString());
OidcData data = PENDING_OIDC.get(sr.getState().toString());

if (data == null) {
return HttpResponse.ofCode(400).withHtml(
"Your oidc provider sent invalid state data. Try again or contact your oidc admin"
Expand Down Expand Up @@ -331,13 +340,13 @@ public static HttpResponse oidcDeleteCallback(OidcProvider provider, URI request
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");
}
} catch (BadJOSEException e) {
System.err.println("Invalid token received: " + e);
return HttpResponse.ofCode(400).withHtml("Received a bad token. Please try again");
} catch (JOSEException e) {
System.err.println("Token processing error: " + e);
return HttpResponse.ofCode(500).withHtml("Internal processing error. Please try again");
}

Long authTime = (Long) claims.getNumberClaim("auth_time");

Expand All @@ -356,6 +365,7 @@ public static HttpResponse oidcDeleteCallback(OidcProvider provider, URI request
s.remove(DatabaseHelper.getUserFromSession(session));
tr.commit();
}

return HttpResponse.redirect302(Constants.FRONTEND_URL + "/preferences?deleted=" + session);
}

Expand Down
Loading