-
Notifications
You must be signed in to change notification settings - Fork 1
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
Cascade delete #64
Cascade delete #64
Changes from 14 commits
0a79dd6
c94a52b
3fbc850
24acb0b
3d70aa2
993a7ba
1fa79e7
ab88847
6ff1fd1
6e6e3a0
39bfee4
84608b7
942c804
4ae3945
869713d
e4cdb9a
d4ecd7a
167af9b
32f0340
69c562f
4f43685
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,16 +9,22 @@ | |
import com.auth0.jwt.algorithms.Algorithm; | ||
import com.auth0.jwt.exceptions.JWTVerificationException; | ||
import com.auth0.jwt.interfaces.DecodedJWT; | ||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import org.eclipse.jetty.http.HttpStatus; | ||
import org.opentripplanner.middleware.models.AbstractUser; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import spark.HaltException; | ||
import spark.Request; | ||
import spark.Response; | ||
|
||
import java.security.interfaces.RSAPublicKey; | ||
|
||
import static org.opentripplanner.middleware.OtpMiddlewareMain.getConfigPropertyAsText; | ||
import static org.opentripplanner.middleware.OtpMiddlewareMain.hasConfigProperty; | ||
import static org.opentripplanner.middleware.controllers.api.ApiUserController.API_USER_PATH; | ||
import static org.opentripplanner.middleware.controllers.api.OtpUserController.OTP_USER_PATH; | ||
import static org.opentripplanner.middleware.utils.JsonUtils.getPOJOFromRequestBody; | ||
import static org.opentripplanner.middleware.utils.JsonUtils.logMessageAndHalt; | ||
|
||
/** | ||
|
@@ -53,18 +59,48 @@ public static void checkUser(Request req) { | |
try { | ||
DecodedJWT jwt = verifier.verify(token); | ||
Auth0UserProfile profile = new Auth0UserProfile(jwt); | ||
if (!isValidUser(profile)) { | ||
landonreed marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// If not a valid user (and not creating an OTP/API user for self), halt the request. Note: creating an | ||
// admin user requires that the requester is an admin (checkUserIsAdmin must be passed), so this is not | ||
// a concern for that method/controller. | ||
if (!isCreatingSelf(req, profile)) { | ||
logMessageAndHalt(req, HttpStatus.NOT_FOUND_404, "Unknown user."); | ||
} | ||
} | ||
// The user attribute is used on the server side to check user permissions and does not have all of the | ||
// fields that the raw Auth0 profile string does. | ||
addUserToRequest(req, profile); | ||
} catch (JWTVerificationException e) { | ||
// Invalid signature/claims | ||
logMessageAndHalt(req, 401, "Login failed to verify with our authorization provider.", e); | ||
} catch (HaltException e) { | ||
throw e; | ||
} catch (Exception e) { | ||
LOG.warn("Login failed to verify with our authorization provider.", e); | ||
logMessageAndHalt(req, 401, "Could not verify user's token"); | ||
} | ||
} | ||
|
||
/** | ||
* Check for POST requests that are creating an {@link AbstractUser} (a proxy for OTP/API users). | ||
*/ | ||
private static boolean isCreatingSelf(Request req, Auth0UserProfile profile) { | ||
// First, check the request method/path. | ||
String uri = req.uri(); | ||
String method = req.requestMethod(); | ||
if (method.equalsIgnoreCase("POST") && (uri.endsWith(OTP_USER_PATH) || uri.endsWith(API_USER_PATH))) { | ||
// Next, get the user object from the request body, verifying that the Auth0UserId matches. | ||
try { | ||
AbstractUser user = getPOJOFromRequestBody(req, AbstractUser.class); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A piece of code might still be missing here.
{
"auth0UserId":"auth0|5f**************",
"email":"[email protected]",
"hasConsentedToTerms":true,
"notificationChannel":"email",
"phoneNumber":"",
"savedLocations":[],
"storeTripHistory":false
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The easiest workaround is probably to pass There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, fixed and tested. 869713d |
||
return profile.auth0UserId.equals(user.auth0UserId); | ||
} catch (JsonProcessingException e) { | ||
LOG.warn("Could not parse user object from request."); | ||
return false; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
public static boolean isAuthHeaderPresent(Request req) { | ||
final String authHeader = req.headers("Authorization"); | ||
return authHeader != null; | ||
|
@@ -106,7 +142,7 @@ public static void addUserToRequest(Request req, Auth0UserProfile user) { | |
* Get user profile from Spark Request object | ||
*/ | ||
public static Auth0UserProfile getUserFromRequest(Request req) { | ||
return (Auth0UserProfile) req.attribute("user"); | ||
return req.attribute("user"); | ||
} | ||
|
||
/** | ||
|
@@ -169,40 +205,30 @@ public static boolean authDisabled() { | |
} | ||
|
||
/** | ||
* Confirm that the user exists | ||
* Confirm that the user exists in at least one of the MongoDB user collections. | ||
*/ | ||
private static Auth0UserProfile isValidUser(Request request) { | ||
|
||
Auth0UserProfile profile = getUserFromRequest(request); | ||
if (profile == null || (profile.adminUser == null && profile.otpUser == null && profile.apiUser == null)) { | ||
logMessageAndHalt(request, HttpStatus.NOT_FOUND_404, "Unknown user."); | ||
} | ||
|
||
return profile; | ||
private static boolean isValidUser(Auth0UserProfile profile) { | ||
return profile != null && (profile.adminUser != null || profile.otpUser != null || profile.apiUser != null); | ||
} | ||
|
||
/** | ||
* Confirm that the user's actions are on their items if not admin. | ||
*/ | ||
public static void isAuthorized(String userId, Request request) { | ||
|
||
Auth0UserProfile profile = isValidUser(request); | ||
|
||
Auth0UserProfile profile = getUserFromRequest(request); | ||
// let admin do anything | ||
if (profile.adminUser != null) { | ||
return; | ||
} | ||
|
||
// If userId is defined, it must be set to a value associated with the user. | ||
if (userId != null) { | ||
if (profile.otpUser != null && profile.otpUser.id.equals(userId)) { | ||
return; | ||
} | ||
|
||
if (profile.apiUser != null && profile.apiUser.id.equals(userId)) { | ||
return; | ||
} | ||
} | ||
|
||
logMessageAndHalt(request, HttpStatus.FORBIDDEN_403, "Unauthorized access."); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These new variables should appear in
env.yml.tmp
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that's the case if they're only intended for e2e.