Skip to content

Instantly share code, notes, and snippets.

@th0br0
Last active April 13, 2016 10:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save th0br0/bd80a3e2b7f261912461c94fe00e5033 to your computer and use it in GitHub Desktop.
Save th0br0/bd80a3e2b7f261912461c94fe00e5033 to your computer and use it in GitHub Desktop.
Auth Flow Example
package policycompass.fcmmanager.auth;
public class AuthenticationFilter implements ResourceFilter, ContainerRequestFilter {
private final static ADHOCRACY_URL = "http://adhocracy-frontend-stage.policycompass.eu/api";
private final static ADHOCRACY_GODS_URL = "http://adhocracy-frontend-stage.policycompass.eu/api/principals/groups/gods/";
AuthenticationFilter() {
}
public ContainerRequestFilter getRequestFilter() {
return this;
}
public ContainerResponseFilter getResponseFilter() {
return null;
}
private List<String> getAdhocracyGods() {
Client c = Client.create();
WebResource resource = c.resource(ADHOCRACY_GODS_URL);
ClientResponse response = resource.accept(MediaType.APPLICATION_JSON_TYPE).get(ClientResponse.class);
// This might not work out of the box. Or be missing dependencies. Needs to be checked.
JSONObject json = response.getEntity(JSONObject.class);
JSONArray users = json.getJSONObject("data").getJSONObject("adhocracy_core.sheets.principal.IGroup").getJSONArray("users");
List<String> gods = new ArrayList<>();
for(int i = 0; i < users.length(); i++)
gods.add(users.getString(i));
return gods;
}
public ContainerRequest filter(ContainerRequest request) {
// We require a valid user for this endpoint.
String userPath = request.getHeaderValue("X-User-Path");
String userToken = request.getHeaderValue("X-User-Token");
if(userPath == null || userToken == null)
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
// Validate userPath & userToken.adhocracy_core.sheets.principal.IGroup
// FIXME this doesn't use HTTPS for session validation. This is a NOGO.
// XXX Creating a new client instance for each request might be resource intensive. Investigate.
Client c = Client.create();
WebResource resource = c.resource(ADHOCRACY_URL);
ClientResponse response = resource.accept(MediaType.APPLICATION_JSON_TYPE)
.header("X-User-Path", userPath)
.header("X-User-Token", userToken).get(ClientResponse.class);
// This might not work out of the box. Or be missing dependencies. Needs to be checked.
JSONObject json = response.getEntity(JSONObject.class);
if(json.has("errors"))
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
// Check that user is neither hidden or deleted.
JSONObject metadata = json.getJSONObject("data").getJSONObject("adhocracy_core.sheets.metadata.IMetadata");
if(metadata.getString("deleted").equals("false") || metadata.getString("hidden").equals("false"))
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
// User is validated to exist.
List<String> gods = getAdhocracyGods();
boolean userIsGod = gods.contains(userPath);
request.getProperties().put("X-User-Path", userPath);
if(userIsGod)
request.getProperties().put("X-User-Is-God", true);
return request;
}
}
package policycompass.fcmmanager.auth;
public class AuthFilterFactory implements ResourceFilterFactory {
@Context
private UriInfo uriInfo;
@Override
public List create(AbstractMethod method) {
RequiresAuthentication annotation = method.getAnnotation(RequiresAuthentication.class);
if(annotation != null)
return Collections.singletonList(new AuthenticationFilter());
else return Collections.singletonList()
}
}
// ...
@DELETE
@Path("/models/{id}")
@Produces({MediaType.APPLICATION_JSON})
@RequiresAuthentication
public Response deleteFCMModel(@PathParam("id") int id, @Context Request request) {
ContainerRequest containerRequest = (ContainerRequest) request;
String userPath = (String) containerRequest.getProperties().get("X-User-Path");
boolean userIsGod = containerRequest.getProperties().has("X-User-Is-God");
FCMModels.deleteFCMModel(id, userPath, userIsGod);
return Response.status(204).build();
}
// ...
package policycompass.fcmmanager.auth;
@Retention(RetentionPolicy.RUNTIME) // Make this annotation accessible at runtime via reflection.
@Target({ElementType.METHOD}) // This annotation can only be applied to class methods.
public @interface RequiresAuthentication {}
<!-- ... (inside the servlet definition) -->
<init-param>
<param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
<param-value>policycompass.fcmmanager.auth.AuthRequestFilterFactory</param-value>
</init-param>
<!-- ... -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment