@ -1,27 +1,29 @@
package org.gcube.portlet.user.my_vres.server ;
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor ;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor ;
import java.util.ArrayList ;
import java.util.Collections ;
import java.util.LinkedHashMap ;
import java.util.List ;
import java.util.UUID ;
import javax.servlet.http.HttpServletRequest ;
import org.apache.http.HttpResponse ;
import org.apache.http.client.methods.HttpPost ;
import org.apache.http.client.params.HttpClientParams ;
import org.apache.http.entity.ContentType ;
import org.apache.http.entity.StringEntity ;
import org.apache.http.impl.client.CloseableHttpClient ;
import org.apache.http.impl.client.HttpClientBuilder ;
import org.apache.http.impl.client.LaxRedirectStrategy ;
import org.gcube.common.portal.GCubePortalConstants ;
import org.gcube.common.portal.PortalContext ;
import org.gcube.common.resources.gcore.ServiceEndpoint ;
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint ;
import org.gcube.common.resources.gcore.utils.Group ;
import org.gcube.common.scope.api.ScopeProvider ;
import org.gcube.portal.auth.AuthUtil ;
import org.gcube.portlet.user.my_vres.client.MyVREsService ;
import org.gcube.portlet.user.my_vres.shared.AuthorizationBean ;
import org.gcube.portlet.user.my_vres.shared.UserBelonging ;
import org.gcube.portlet.user.my_vres.shared.VRE ;
import org.gcube.resources.discovery.client.api.DiscoveryClient ;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery ;
import org.gcube.vomanagement.usermanagement.GroupManager ;
import org.gcube.vomanagement.usermanagement.exception.GroupRetrievalFault ;
import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException ;
@ -32,6 +34,7 @@ import org.gcube.vomanagement.usermanagement.model.GCubeGroup;
import org.gcube.vomanagement.usermanagement.model.GCubeUser ;
import org.gcube.vomanagement.usermanagement.model.VirtualGroup ;
import org.gcube.vomanagement.usermanagement.util.ManagementUtils ;
import org.json.simple.JSONObject ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
@ -260,16 +263,27 @@ public class MyVREsServiceImpl extends RemoteServiceServlet implements MyVREsSer
}
@Override
public AuthorizationBean getUserToken ( String context , String state , String clientId , String redirectURL ) {
public AuthorizationBean getUserQualifierToken ( String context , String state , String clientId , String redirectURL ) {
String infraName = PortalContext . getConfiguration ( ) . getInfrastructureName ( ) ;
if ( clientId = = null | | clientId . compareTo ( "" ) = = 0 ) {
return new AuthorizationBean ( null , null , false , "client_id is null, you MUST register your application to allow users connect with their D4Science Credentials" ) ;
}
if ( redirectURL = = null | | redirectURL . compareTo ( "" ) = = 0 ) {
return new AuthorizationBean ( null , null , false , "authorised redirect URL is null, you MUST pass the authorisedRedirectURI related to your client_id registered application to allow users connect with their D4Science Credentials" ) ;
}
List < String > authorisedRedirectURLs = getAuthorisedRedirectURLsFromIs ( clientId ) ;
ServiceEndpoint authorisedApp = null ;
try {
authorisedApp = AuthUtil . getAuthorisedApplicationInfoFromIsICClient ( infraName , clientId ) ;
} catch ( Exception e1 ) {
e1 . printStackTrace ( ) ;
return new AuthorizationBean ( null , null , false , "Ops!, we failed to check if (" + clientId + ") is a valid clientId, some error occurred, please try in a few minutes. If the problem persists please open an incident ticket" ) ;
}
if ( authorisedApp = = null ) {
return new AuthorizationBean ( null , null , false , "Your application (" + clientId + ") is not authorized in the infrastructure" ) ;
}
List < String > authorisedRedirectURLs = AuthUtil . getAuthorisedRedirectURLsFromIs ( authorisedApp ) ;
if ( authorisedRedirectURLs = = null | | authorisedRedirectURLs . isEmpty ( ) ) {
return new AuthorizationBean ( null , null , false , "Your application (" + clientId + ") is not registered or there are no authorised redirect URLs registered for your application" ) ;
return new AuthorizationBean ( null , null , false , "Your application (" + clientId + ") have no authorised redirect URLs ") ;
}
boolean urlAuthorised = false ;
for ( String authorisedURL : authorisedRedirectURLs )
@ -310,63 +324,70 @@ public class MyVREsServiceImpl extends RemoteServiceServlet implements MyVREsSer
_log . error ( "Something wrong in retrieving the user" ) ;
return new AuthorizationBean ( null , null , false , "Something wrong in retrieving the logged in user, is session expired?" ) ;
}
String token = pContext . getCurrentUserToken ( context , username ) ;
if ( token = = null ) {
_log . error ( "Something wrong in retrieving the user token in this context: " + context + " username=" + username ) ;
return new AuthorizationBean ( null , null , false , "Something wrong in retrieving the user token in this context: " + context + " username=" + username ) ;
//no errors, proceed to step 2
String userToken = pContext . getCurrentUserToken ( context , username ) ;
String appName = authorisedApp . profile ( ) . name ( ) ;
String qToken = AuthUtil . generateAuthorizationQualifierToken ( appName , userToken ) ;
_log . info ( "Received qualifier token for useer " + username + "=" + qToken ) ;
if ( qToken = = null ) {
_log . error ( "Something wrong in retrieving the user qualifier token in this context: " + context + " username=" + username ) ;
return new AuthorizationBean ( null , null , false , "Something wrong in retrieving the user qualifier token in this context: " + context + " username=" + username ) ;
}
_log . debug ( "Authorisation OAUTH returning user token in this context: " + context + " username=" + username ) ;
return new AuthorizationBean ( token , state , true , null ) ;
String tempCode = UUID . randomUUID ( ) . toString ( ) ;
if ( ! authorizeApplication ( infraName , qToken , tempCode , clientId , redirectURL ) ) {
_log . error ( "Something wrong in authorizing this application in this context: " + context ) ;
return new AuthorizationBean ( null , null , false , "Something wrong in authorizing this application in this context: " + context + " an error occurred in the oAuth Service" ) ;
}
_log . debug ( "Authorisation OAUTH 2 OK returning temporary code in this context: " + context + " username=" + username ) ;
return new AuthorizationBean ( tempCode , state , true , null ) ;
}
//TODO: check the query, it doesn work
private List < ServiceEndpoint > getPortalConfigurationFromIS ( String infrastructureName , String clientId ) throws Exception {
String scope = "/" + infrastructureName ;
String currScope = ScopeProvider . instance . get ( ) ;
ScopeProvider . instance . set ( scope ) ;
SimpleQuery query = queryFor ( ServiceEndpoint . class ) ;
query . addCondition ( "$resource/Profile/Category/text() eq '" + SERVICE_ENDPOINT_CATEGORY + "'" ) ;
query . addCondition ( "$resource/Profile/Name/text() eq '" + clientId + "'" ) ;
DiscoveryClient < ServiceEndpoint > client = clientFor ( ServiceEndpoint . class ) ;
List < ServiceEndpoint > toReturn = client . submit ( query ) ;
ScopeProvider . instance . set ( currScope ) ;
return toReturn ;
}
/ * *
* look for the clientId AccessEndpoint passes as parameter
* @param gatewayName
* @param clientId
* @return the client secret related to the id , or null if non existent
* we post to the auth service a temporary code to be used within seconds from the application
* @param qToken the user qualifier token
* @param tempCode the temporary code
* @param clientId tha app id
* @param redirectURI the authorised redirect URI
* @return
* /
private List < String > getAuthorisedRedirectURLsFromIs ( String clientId ) {
PortalContext pContext = PortalContext . getConfiguration ( ) ;
String scope = "/" + pContext . getInfrastructureName ( ) ;
List< String > autRedirectURLs = new ArrayList < > ( ) ;
@SuppressWarnings ( "unchecked" )
private boolean authorizeApplication ( String infrastructureName , String qToken , String tempCode , String clientId , String redirectURL ) {
String fullPath2oAuthService = null ;
try {
List < ServiceEndpoint > list = getPortalConfigurationFromIS ( pContext . getInfrastructureName ( ) , clientId ) ;
if ( list . size ( ) > 1 ) {
_log . error ( "Too many Service Endpoints having name " + clientId + " in this scope having Category " + SERVICE_ENDPOINT_CATEGORY ) ;
}
else if ( list . size ( ) = = 0 ) {
_log . warn ( "There is no Service Endpoint having name " + clientId + " and Category " + SERVICE_ENDPOINT_CATEGORY + " in this scope: " + scope ) ;
}
else {
for ( ServiceEndpoint res : list ) {
Group < AccessPoint > apGroup = res . profile ( ) . accessPoints ( ) ;
AccessPoint [ ] accessPoints = ( AccessPoint [ ] ) apGroup . toArray ( new AccessPoint [ apGroup . size ( ) ] ) ;
for ( int i = 0 ; i < accessPoints . length ; i + + ) {
if ( accessPoints [ i ] . name ( ) . compareTo ( REDIRECT_URL ) = = 0 ) {
AccessPoint found = accessPoints [ i ] ;
autRedirectURLs . add ( found . address ( ) ) ;
}
}
}
fullPath2oAuthService = AuthUtil . getOAuthServiceEndPoint ( infrastructureName ) +
"/v2/push-authentication-code?gcube-token=" + qToken ;
} catch ( Exception e1 ) {
_log . error ( "failed to discover oauth service endpoint " ) ;
return false ;
}
fullPath2oAuthService = fullPath2oAuthService . replaceAll ( "http" , "https" ) ;
fullPath2oAuthService = fullPath2oAuthService . replaceAll ( "80" , "443" ) ;
JSONObject object = new JSONObject ( ) ;
object . put ( "code" , tempCode ) ;
object . put ( "redirect_uri" , redirectURL ) ;
object . put ( "client_id" , clientId ) ;
try ( CloseableHttpClient httpClient = HttpClientBuilder . create ( ) . setRedirectStrategy ( new LaxRedirectStrategy ( ) ) . build ( ) ) {
HttpPost httpPostRequest = new HttpPost ( fullPath2oAuthService ) ;
httpPostRequest . addHeader ( "Content-type" , "application/json" ) ;
StringEntity params = new StringEntity ( object . toJSONString ( ) , ContentType . APPLICATION_JSON ) ;
httpPostRequest . setEntity ( params ) ;
HttpResponse response = httpClient . execute ( httpPostRequest ) ;
if ( response . getStatusLine ( ) . getStatusCode ( ) < 200 | | response . getStatusLine ( ) . getStatusCode ( ) > = 300 ) {
_log . error ( "failed to patch the product. response status line from "
+ fullPath2oAuthService + " was: " + response . getStatusLine ( ) ) ;
return false ;
}
} catch ( Exception e ) {
e . printStackTrace ( ) ;
return null ;
} catch ( Exception e ) {
_log . error ( "Failed to perform request" , e ) ;
}
return autRedirectURLs ;
return true ;
}
}