package eu.dnetlib.openaire.usermanagement.api; import com.fasterxml.jackson.core.JsonProcessingException; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import eu.dnetlib.openaire.user.dao.SQLMigrationUserDAO; import eu.dnetlib.openaire.user.ldap.MUserActionsLDAP; import eu.dnetlib.openaire.user.pojos.migration.LDAPUser; import eu.dnetlib.openaire.user.store.DataSourceConnector; import eu.dnetlib.openaire.usermanagement.authorization.AuthoritiesMapper; import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.log4j.Logger; import org.mitre.openid.connect.model.OIDCAuthenticationToken; import org.mitre.openid.connect.model.UserInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.*; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.RestTemplate; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; /** * Created by sofia on 24/11/2016. */ @Component(value = "test3service") @Path("/users") public class Test3Service { private static final Logger logger = Logger.getLogger(Test3Service.class); public static final String errorMessage = "{ \"status\" : \"error\", \"code\" : \"%s\", \"message\" : \"%s\", \"description\" : \"%s\" }"; @Autowired private SQLMigrationUserDAO sqlMigrationUserDAO; @Autowired private MUserActionsLDAP mUserActionsLDAP; @Autowired private DataSourceConnector dataSourceConnector; @Value("${oidc.issuer}") private String issuer; @Value("${oidc.secret}") private String secret; @Value("${oidc.id}") private String id; @GET @PreAuthorize("hasAuthority('ROLE_USER')") @Path("/getRefreshToken") public Response getRefreshToken(){ OIDCAuthenticationToken authentication = (OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); return Response.status(200).entity(authentication.getRefreshTokenValue()).build(); } @GET @PreAuthorize("hasAuthority('ROLE_USER')") @Path("/getJWTToken") public Response getAccessToken(){ OIDCAuthenticationToken authentication = (OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); return Response.status(200).entity(authentication.getAccessTokenValue()).build(); } @GET @Path("/getAccessToken") @Produces(MediaType.APPLICATION_JSON) public Response getAccessTokenFromRefreshToken(@Context final HttpServletRequest request, @QueryParam("refreshToken") String refreshToken){ if (refreshToken == null || refreshToken.isEmpty()) { return Response.status(Response.Status.BAD_REQUEST) .entity(String.format(errorMessage, 400, "Bad Request", "Missing refreshToken parameter")) .type(MediaType.APPLICATION_JSON).build(); } CloseableHttpClient httpclient = HttpClients.createDefault(); HttpPost httppost = new HttpPost(issuer+"/token"); // Request parameters and other properties. List params = new ArrayList(); params.add(new BasicNameValuePair("client_id", id)); params.add(new BasicNameValuePair("client_secret", secret)); params.add(new BasicNameValuePair("grant_type", "refresh_token")); params.add(new BasicNameValuePair("refresh_token", refreshToken)); params.add(new BasicNameValuePair("scope", "openid")); HttpResponse response = null; try { httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); //Execute and get the response. response = httpclient.execute(httppost); org.apache.http.HttpEntity entity = response.getEntity(); if (response.getStatusLine().getStatusCode() == 401) { return Response.status(Response.Status.UNAUTHORIZED) .entity(String.format(errorMessage, 401, "Unauthorised", "Invalid refreshToken token " + refreshToken)) .type(MediaType.APPLICATION_JSON).build(); } String serverMessage = IOUtils.toString(entity.getContent(), StandardCharsets.UTF_8.name()); return Response.status(response.getStatusLine().getStatusCode()) .entity(serverMessage).type(MediaType.APPLICATION_JSON).build(); } catch (UnsupportedEncodingException uee) { logger.error(uee); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(String.format(errorMessage, 500, "Fail to get access token.", uee.getMessage())) .type(MediaType.APPLICATION_JSON).build(); } catch (IOException ioe) { logger.error(ioe); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(String.format(errorMessage, 500, "Fail to get access token.", ioe.getMessage())) .type(MediaType.APPLICATION_JSON).build(); } } @GET @Path("/getToken") @Produces(MediaType.APPLICATION_JSON) public Response getToken(@QueryParam("accessToken") String accessToken){ logger.debug("Refresh token " + accessToken); CloseableHttpClient httpclient = HttpClients.createDefault(); HttpPost httppost = new HttpPost(issuer+"/token"); // Request parameters and other properties. List params = new ArrayList(); params.add(new BasicNameValuePair("client_id", id)); params.add(new BasicNameValuePair("client_secret", secret)); params.add(new BasicNameValuePair("grant_type", "refresh_token")); params.add(new BasicNameValuePair("refresh_token", accessToken)); params.add(new BasicNameValuePair("scope", "openid")); try { httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); //Execute and get the response. HttpResponse response = null; response = httpclient.execute(httppost); org.apache.http.HttpEntity entity = response.getEntity(); if (entity != null) { try (InputStream instream = entity.getContent()) { logger.debug(IOUtils.toString(instream, StandardCharsets.UTF_8.name())); } } } catch (UnsupportedEncodingException uee) { logger.error(uee); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(String.format(errorMessage, 500, "Fail to get access token.", uee.getMessage())) .type(MediaType.APPLICATION_JSON).build(); } catch (IOException ioe) { logger.error(ioe); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(String.format(errorMessage, 500, "Fail to get access token.", ioe.getMessage())) .type(MediaType.APPLICATION_JSON).build(); } return Response.status(200).type(MediaType.APPLICATION_JSON).build(); } @GET @Path("/getUserInfo") @Produces(MediaType.APPLICATION_JSON) public Response getUserInfo(@QueryParam("accessToken") String accessToken) throws JsonProcessingException { //return Response.status(404).entity(compose404Message("This is a test message.")).type(MediaType.APPLICATION_JSON).build(); // call aai with accessToken logger.info(accessToken); RestTemplate restTemplate = new RestTemplate(); restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){ protected boolean hasError(HttpStatus statusCode) { return false; }}); HttpHeaders headers = new HttpHeaders(); headers.add("Authorization","Bearer " + accessToken); HttpEntity request = new HttpEntity<>(headers); //logger.info(restTemplate.exchange(fooResourceUrl, HttpMethod.GET, request, Object.class)); ResponseEntity response = restTemplate.exchange(issuer +"userinfo", HttpMethod.GET, request, String.class); if(response.getStatusCode() == HttpStatus.OK) { JsonObject userInfo = new JsonParser().parse(response.getBody()).getAsJsonObject(); JsonArray roles = new JsonArray(); AuthoritiesMapper.map(userInfo.get("edu_person_entitlements").getAsJsonArray()).forEach(grantedAuthority -> { roles.add(grantedAuthority.getAuthority()); }); userInfo.add("roles", roles); return Response.status(response.getStatusCode().value()).entity(userInfo.toString()).type(MediaType.APPLICATION_JSON).build(); } else { return Response.status(response.getStatusCode().value()).entity(response.getBody()).type(MediaType.APPLICATION_JSON).build(); } } @GET @Path("/getUser") @Produces(MediaType.APPLICATION_JSON) public Response getUser() { JsonObject userInfoJson = new JsonObject(); try { OIDCAuthenticationToken authentication = null; try { authentication = (OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); }catch (Exception e){ logger.info("Try to get User info - no context found "); return Response.status(404).entity(compose404Message("Get User info: no context found ")).type(MediaType.APPLICATION_JSON).build(); } UserInfo userInfo = authentication.getUserInfo(); if(userInfo == null){ return Response.status(404).entity(compose404Message("Get User info: user info is null ")).type(MediaType.APPLICATION_JSON).build(); } logger.info("Get User:\n name: " + authentication.getUserInfo().getGivenName() + " " + authentication.getUserInfo().getFamilyName()); userInfoJson.addProperty("sub", userInfo.getSub()); userInfoJson.addProperty("name", userInfo.getName()); userInfoJson.addProperty("given_name", userInfo.getGivenName()); userInfoJson.addProperty("family_name", userInfo.getFamilyName()); userInfoJson.addProperty("email", userInfo.getEmail()); JsonArray roles = new JsonArray(); authentication.getAuthorities().forEach(grantedAuthority -> { roles.add(grantedAuthority.getAuthority()); }); userInfoJson.add("roles", roles); }catch (Exception e){ logger.error("Get User info: An error occurred ",e); return Response.status(500).entity(compose500Message("Get User info: An error occurred ",e)).type(MediaType.APPLICATION_JSON).build(); } return Response.status(200).entity(userInfoJson.toString()).type(MediaType.APPLICATION_JSON).build(); } /* @GET @Path("/katerina") @Produces(MediaType.APPLICATION_JSON) //@PreAuthorize("hasRole('ROLE_USER')") @PreAuthorize("hasAuthority('urn:geant:openaire.eu:group:Registered+User#aai.openaire.eu')") public Response getKaterina() { return Response.status(200).build(); } @GET @Path("/skata") @Produces(MediaType.APPLICATION_JSON) @PreAuthorize("hasRole('ROLE_USER')") public Response getKaterina2() { return Response.status(200).build(); } @GET @Path("/skata2") @Produces(MediaType.APPLICATION_JSON) @PreAuthorize("hasAuthority('skata')") public Response getKaterina3() { return Response.status(200).build(); } @GET @Path("/me") //@Produces(MediaType.APPLICATION_JSON) public Response getKaterina(@AuthenticationPrincipal UserDetails userDetails) { //return Response.status(200).entity(userDetails).type(MediaType.APPLICATION_JSON).build(); return Response.status(200).build(); } */ /* JSON Utility Methods */ private String compose401Message(String message) { return "{ \"status\" : \"error\", \"code\" : \"401\", \"message\" : \" " + message +" \" }"; } private String compose404Message(String message) { return "{ \"status\" : \"error\", \"code\" : \"404\", \"message\" : \" " + message +" \" }"; } private String compose500Message(String message, Exception exception) { return "{ \"status\" : \"fail\", \"code\" : \"500\", \"message\" : \" " + message + "\", " + "\"description\" : \""+ exception.getMessage() +"\" }"; } private String composeDataResponse(LDAPUser user) { return " { \"status\" : \"success\", \"code\": \"200\", " + "\"data\" : " + new Gson().toJson(user) + " }"; } private String composeDataResponse(String fullname) { return " { \"status\" : \"success\", \"code\": \"200\", " + "\"data\" : " + new Gson().toJson(fullname) + " }"; } }