Skip to content

Commit

Permalink
[ALS-4793] Initial impl for open access auth
Browse files Browse the repository at this point in the history
  • Loading branch information
Gcolon021 committed Aug 3, 2023
1 parent 3be54de commit df2a5f5
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@


import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.MapType;
import edu.harvard.hms.dbmi.avillach.auth.data.entity.Connection;
import edu.harvard.hms.dbmi.avillach.auth.data.entity.Privilege;
import edu.harvard.hms.dbmi.avillach.auth.data.entity.Role;
Expand All @@ -11,7 +10,6 @@
import edu.harvard.hms.dbmi.avillach.auth.data.repository.RoleRepository;
import edu.harvard.hms.dbmi.avillach.auth.rest.TokenService;
import io.swagger.jaxrs.config.BeanConfig;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
Expand All @@ -28,13 +26,10 @@
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.SecurityContext;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import javax.net.ssl.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static edu.harvard.hms.dbmi.avillach.auth.utils.AuthNaming.AuthRoleNaming.ADMIN;
import static edu.harvard.hms.dbmi.avillach.auth.utils.AuthNaming.AuthRoleNaming.SUPER_ADMIN;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@
import javax.persistence.NonUniqueResultException;
import javax.persistence.criteria.*;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -99,10 +96,6 @@ public User findOrCreate(User inputUser) {

private User createUser(User inputUser) {
String subject = inputUser.getSubject();
// if (subject == null && userId == null){
// logger.error("createUser() cannot create user when both subject and userId are null");
// return null;
// }
logger.debug("createUser() creating user, subject: " + subject + " ......");
em().persist(inputUser);

Expand Down Expand Up @@ -161,4 +154,42 @@ public boolean checkAgainstTOSDate(String userId){
.getResultList().isEmpty();
}

/**
*
* @param uuid the uuid of the user to find
* @return the user with the given uuid, or null if no user is found
*/
public User findByUUID(UUID uuid) {
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
Root<User> queryRoot = query.from(User.class);
query.select(queryRoot);
CriteriaBuilder cb = cb();
try {
return em.createQuery(query
.where(
eq(cb, queryRoot, "uuid", uuid)))
.getSingleResult();
} catch (NoResultException e){
logger.error("findByUUID() " + e.getClass().getSimpleName() + ": " + e.getMessage());
}

return null;
}

public User createOpenAccessUser() {
// I can either use the user subject combined with a random string, or I can use the uuid of the user
// after I create the user. I think I will use the uuid of the user after I create the user.

// create a new user
User user = new User();
em().persist(user);

// We should have a user now, so get the user by uuid
User result = getById(user.getUuid());
result.setSubject("open_access|" + result.getUuid().toString());
result.setRoles(new HashSet<>());
em().merge(result);

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package edu.harvard.hms.dbmi.avillach.auth.rest;

import edu.harvard.hms.dbmi.avillach.auth.service.auth.OpenAuthenticationService;
import edu.harvard.hms.dbmi.avillach.auth.service.auth.AuthenticationService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.Map;

/**
* <p>The authentication endpoint for PSAMA.</p>
*/
@Api
@Path("/open")
@Consumes("application/json")
@Produces("application/json")
public class OpenAuthService {

private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Inject
private OpenAuthenticationService openAuthenticationService;

// I went with a new endpoint instead of setting a new idp_provider because open_access isn't really an idp_provider.
// Secondly there was already a default authentication endpoint, so I didn't want to change that.
@ApiOperation(value = "The authentication endpoint for retrieving a valid user token")
@POST
@Path("/authentication")
public Response authentication(@Context UriInfo uriInfo, @ApiParam(required = true, value = "A json object that includes all Oauth authentication needs, for example, access_token and redirectURI") Map<String, String> authRequest) {
logger.debug("authentication() starting...");

return openAuthenticationService.authenticate(uriInfo, authRequest);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -519,5 +519,4 @@ private void checkAssociation(List<User> users) throws ProtocolException{
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package edu.harvard.hms.dbmi.avillach.auth.service.auth;

import edu.harvard.dbmi.avillach.util.response.PICSUREResponse;
import edu.harvard.hms.dbmi.avillach.auth.data.entity.User;
import edu.harvard.hms.dbmi.avillach.auth.data.repository.UserRepository;
import edu.harvard.hms.dbmi.avillach.auth.rest.UserService;
import edu.harvard.hms.dbmi.avillach.auth.utils.AuthUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class OpenAuthenticationService {

private final Logger logger = LoggerFactory.getLogger(OpenAuthenticationService.class);

@Inject
private UserRepository userRepository;

@Inject
AuthUtils authUtil;

public Response authenticate(UriInfo uriInfo, Map<String, String> authRequest) {
String userUUID = authRequest.get("UUID");
User current_user = null;

if (userUUID == null || userUUID.isEmpty()) {
UUID uuid = UUID.fromString(userUUID);

// Get the user from the database
current_user = userRepository.findByUUID(uuid);
}


if (current_user == null) {
current_user = userRepository.createOpenAccessUser();

//clear some cache entries if we register a new login
AuthorizationService.clearCache(current_user);
UserService.clearCache(current_user);
}

HashMap<String, Object> claims = new HashMap<>();
claims.put("sub", current_user.getUuid().toString());
claims.put("email", current_user.getSubject());
HashMap<String, String> responseMap = authUtil.getUserProfileResponse(claims);

logger.info("LOGIN SUCCESS ___ " + current_user.getEmail() + ":" + current_user.getUuid().toString() + " ___ Authorization will expire at ___ " + responseMap.get("expirationDate") + "___");

return PICSUREResponse.success(responseMap);
}
}

0 comments on commit df2a5f5

Please sign in to comment.