@ -71,6 +71,23 @@ public class OpenIdConnectRESTHelper {
public static JWTToken queryClientToken ( String clientId , String clientSecret , URL tokenURL )
throws OpenIdConnectRESTHelperException {
return queryClientToken ( clientId , clientSecret , tokenURL , null ) ;
}
/ * *
* Queries from the OIDC server an OIDC access token , by using provided clientId and client secret .
*
* @param clientId the client id
* @param clientSecret the client secret
* @param tokenUrl the token endpoint { @link URL } of the OIDC server
* @param extraHeaders extra HTTP headers to add to the request ( e . g . < code > X - D4Science - Context < / code > custom header ) , may be < code > null < / code >
* @return the issued token
* @throws OpenIdConnectRESTHelperException if an error occurs ( also an unauthorized call ) , inspect the exception for details
* /
public static JWTToken queryClientToken ( String clientId , String clientSecret , URL tokenURL ,
Map < String , String > extraHeaders )
throws OpenIdConnectRESTHelperException {
Map < String , List < String > > params = new HashMap < > ( ) ;
params . put ( "grant_type" , Arrays . asList ( "client_credentials" ) ) ;
try {
@ -83,34 +100,41 @@ public class OpenIdConnectRESTHelper {
} catch ( UnsupportedEncodingException e ) {
logger . error ( "Cannot URL encode 'client_secret'" , e ) ;
}
return performQueryTokenWithPOST ( tokenURL , null , params );
return performQueryTokenWithPOST ( tokenURL , null , params , extraHeaders );
}
public static JWTToken queryToken ( String clientId , URL tokenURL , String code , String scope ,
String redirectURI ) throws Exception {
return queryToken ( clientId , tokenURL , code , scope , redirectURI , null ) ;
}
public static JWTToken queryToken ( String clientId , URL tokenURL , String code , String scope ,
String redirectURI , Map < String , String > extraHeaders ) throws Exception {
Map < String , List < String > > params = new HashMap < > ( ) ;
params . put ( "client_id" , Arrays . asList ( URLEncoder . encode ( clientId , "UTF-8" ) ) ) ;
params . put ( "grant_type" , Arrays . asList ( "authorization_code" ) ) ;
params . put ( "scope" , Arrays . asList ( URLEncoder . encode ( scope , "UTF-8" ) ) ) ;
params . put ( "code" , Arrays . asList ( URLEncoder . encode ( code , "UTF-8" ) ) ) ;
params . put ( "redirect_uri" , Arrays . asList ( URLEncoder . encode ( redirectURI , "UTF-8" ) ) ) ;
return performQueryTokenWithPOST ( tokenURL , null , params );
return performQueryTokenWithPOST ( tokenURL , null , params , extraHeaders );
}
protected static JWTToken performQueryTokenWithPOST ( URL tokenURL , String authorization ,
Map < String , List < String > > params ) throws OpenIdConnectRESTHelperException {
return performQueryTokenWithPOST ( tokenURL , authorization , params , null ) ;
return performQueryTokenWithPOST ( tokenURL , authorization , params , null ) ;
}
protected static JWTToken performQueryTokenWithPOST ( URL tokenURL , String authorization ,
Map < String , List < String > > params , Map < String , String > headers ) throws OpenIdConnectRESTHelperException {
Map < String , List < String > > params , Map < String , String > headers ) throws OpenIdConnectRESTHelperException {
logger . debug ( "Querying access token from OIDC server with URL: {}" , tokenURL ) ;
StringBuilder sb ;
try {
HttpURLConnection httpURLConnection = performURLEncodedPOSTSendData ( tokenURL , params , authorization , headers ) ;
HttpURLConnection httpURLConnection = performURLEncodedPOSTSendData ( tokenURL , params , authorization ,
headers ) ;
sb = new StringBuilder ( ) ;
int httpResultCode = httpURLConnection . getResponseCode ( ) ;
@ -149,12 +173,13 @@ public class OpenIdConnectRESTHelper {
}
protected static HttpURLConnection performURLEncodedPOSTSendData ( URL url , Map < String , List < String > > params ,
String authorization ) throws IOException , ProtocolException , UnsupportedEncodingException {
String authorization ) throws IOException , ProtocolException , UnsupportedEncodingException {
return performURLEncodedPOSTSendData ( url , params , authorization , null ) ;
}
protected static HttpURLConnection performURLEncodedPOSTSendData ( URL url , Map < String , List < String > > params ,
String authorization , Map < String , String > headers ) throws IOException , ProtocolException , UnsupportedEncodingException {
String authorization , Map < String , String > headers )
throws IOException , ProtocolException , UnsupportedEncodingException {
HttpURLConnection con = ( HttpURLConnection ) url . openConnection ( ) ;
con . setRequestMethod ( "POST" ) ;
@ -188,7 +213,7 @@ public class OpenIdConnectRESTHelper {
* @param tokenUrl the token endpoint { @link URL } of the OIDC server
* @param clientId the client id
* @param clientSecret the client secret
* @param audience the audience ( context ) where to request the issuing of the ticket
* @param audience the audience ( context ) where to request the issuing of the token ( URLEncoded or not )
* @param permissions a list of permissions , can be < code > null < / code >
* @return the issued token
* @throws OpenIdConnectRESTHelperException if an error occurs ( also an unauthorized call ) , inspect the exception for details
@ -196,36 +221,64 @@ public class OpenIdConnectRESTHelper {
public static JWTToken queryUMAToken ( URL tokenUrl , String clientId , String clientSecret , String audience ,
List < String > permissions ) throws OpenIdConnectRESTHelperException {
return queryUMAToken ( tokenUrl , clientId , clientSecret , audience , permissions , null ) ;
}
/ * *
* Queries from the OIDC server an UMA token , by using provided clientId and client secret for the given audience
* ( context ) , in URLEncoded form or not , and optionally a list of permissions .
*
* @param tokenUrl the token endpoint { @link URL } of the OIDC server
* @param clientId the client id
* @param clientSecret the client secret
* @param audience the audience ( context ) where to request the issuing of the token ( URLEncoded or not )
* @param permissions a list of permissions , can be < code > null < / code >
* @param extraHeaders extra HTTP headers to add to the request ( e . g . < code > X - D4Science - Context < / code > custom header ) , may be < code > null < / code >
* @return the issued token
* @throws OpenIdConnectRESTHelperException if an error occurs ( also an unauthorized call ) , inspect the exception for details
* /
public static JWTToken queryUMAToken ( URL tokenUrl , String clientId , String clientSecret , String audience ,
List < String > permissions , Map < String , String > extraHeaders ) throws OpenIdConnectRESTHelperException {
return queryUMAToken ( tokenUrl ,
"Basic " + Base64 . getEncoder ( ) . encodeToString ( ( clientId + ":" + clientSecret ) . getBytes ( ) ) ,
audience , permissions ) ;
audience , permissions , extraHeaders );
}
/ * *
* Queries from the OIDC server an exchanged token by using provided access token , for the given audience ( context ) ,
* Queries from the OIDC server an UMA token , by using provided access token , for the given audience ( context ) ,
* in URLEncoded form or not , and optionally a list of permissions .
*
* @param tokenUrl the token endpoint { @link URL } of the OIDC server
* @param authorization the auth token ( the access token URLEncoded by the "Bearer " string )
* @param audience the audience ( context ) where to request the issuing of the ticket ( URLEncoded )
* @param audience the audience ( context ) where to request the issuing of the t oken ( URLEncoded or not )
* @param permissions a list of permissions , can be < code > null < / code >
* @return the issued token
* @throws OpenIdConnectRESTHelperException if an error occurs ( also an unauthorized call ) , inspect the exception for details
* /
public static JWTToken queryExchangeToken ( URL tokenUrl , String authorization , String audience , String client_id , String client_secret ,
public static JWTToken query UMA Token( URL tokenUrl , String authorization , String audience ,
List < String > permissions ) throws OpenIdConnectRESTHelperException {
logger . info ( "Queried exchangeToken for context " + audience ) ;
Map < String , List < String > > params = new HashMap < > ( ) ;
return queryUMAToken ( tokenUrl , authorization , audience , permissions , null ) ;
}
params . put ( "subject_token" , Arrays . asList ( authorization ) ) ;
params . put ( "client_id" , Arrays . asList ( client_id ) ) ;
params . put ( "client_secret" , Arrays . asList ( client_secret ) ) ;
params . put ( "grant_type" , Arrays . asList ( "urn:ietf:params:oauth:grant-type:token-exchange" ) ) ;
params . put ( "subject_token_type" , Arrays . asList ( "urn:ietf:params:oauth:token-type:access_token" ) ) ;
params . put ( "requested_token_type" , Arrays . asList ( "urn:ietf:params:oauth:token-type:access_token" ) ) ;
/ * *
* Queries from the OIDC server an UMA token , by using provided access token , for the given audience ( context ) ,
* in URLEncoded form or not , and optionally a list of permissions .
*
* @param tokenUrl the token endpoint { @link URL } of the OIDC server
* @param authorization the auth token ( the access token URLEncoded by the "Bearer " string )
* @param audience the audience ( context ) where to request the issuing of the token ( URLEncoded or not )
* @param permissions a list of permissions , can be < code > null < / code >
* @param extraHeaders extra HTTP headers to add to the request ( e . g . < code > X - D4Science - Context < / code > custom header ) , may be < code > null < / code >
* @return the issued token
* @throws OpenIdConnectRESTHelperException if an error occurs ( also an unauthorized call ) , inspect the exception for details
* /
public static JWTToken queryUMAToken ( URL tokenUrl , String authorization , String audience ,
List < String > permissions , Map < String , String > extraHeaders ) throws OpenIdConnectRESTHelperException {
Map < String , List < String > > params = new HashMap < > ( ) ;
params . put ( "grant_type" , Arrays . asList ( "urn:ietf:params:oauth:grant-type:uma-ticket" ) ) ;
if ( audience . startsWith ( "/" ) ) {
try {
logger . trace ( "Audience was provided in non URL encoded form, encoding it" ) ;
@ -249,54 +302,104 @@ public class OpenIdConnectRESTHelper {
}
} ) . collect ( Collectors . toList ( ) ) ) ;
}
return performQueryTokenWithPOST ( tokenUrl , authorization , params , extraHeaders ) ;
}
/ * *
* Queries from the OIDC server an exchanged token by using provided access token , optionally for the given audience ( context )
* in URLEncoded form or not .
*
* @param tokenUrl the token endpoint { @link URL } of the OIDC server
* @param authorization the auth token ( the access token URLEncoded by the "Bearer " string )
* @param audience the audience ( context ) where to request the issuing of the token ( URLEncoded or not ) , may be < code > null < / code >
* @param clientId the client id
* @param clientSecret the client secret
* @param extraHeaders extra HTTP headers to add to the request ( e . g . < code > X - D4Science - Context < / code > custom header ) , may be < code > null < / code >
* @return the issued token
* @throws OpenIdConnectRESTHelperException if an error occurs ( also an unauthorized call ) , inspect the exception for details
* /
public static JWTToken queryExchangeToken ( URL tokenUrl , String authorization , String audience , String client_id ,
String client_secret , Map < String , String > extraHeaders ) throws OpenIdConnectRESTHelperException {
return queryExchangeToken ( tokenUrl , authorization , audience , client_id , client_secret ,
"urn:ietf:params:oauth:token-type:access_token" , null , extraHeaders ) ;
}
// Map<String, String> headers = new HashMap<>();
// headers.put("X-D4Science-Context", audience);
/ * *
* Queries from the OIDC server an exchanged token by using provided access token , optionally for the given audience ( context )
* in URLEncoded form or not .
*
* @param tokenUrl the token endpoint { @link URL } of the OIDC server
* @param authorization the auth token ( the access token URLEncoded by the "Bearer " string )
* @param audience the audience ( context ) where to request the issuing of the token ( URLEncoded or not ) , may be < code > null < / code >
* @param clientId the client id
* @param clientSecret the client secret
* @param withRefreshToken request also the refresh token ( forced to < code > true < / code > for offline requests )
* @param offline request a refresh token of offline type ( TYP claim )
* @param extraHeaders extra HTTP headers to add to the request ( e . g . < code > X - D4Science - Context < / code > custom header ) , may be < code > null < / code >
* @return the issued token
* @throws OpenIdConnectRESTHelperException if an error occurs ( also an unauthorized call ) , inspect the exception for details
* /
public static JWTToken queryExchangeToken ( URL tokenUrl , String authorization , String audience , String clientId ,
String clientSecret , boolean withRefreshToken , boolean offline , Map < String , String > extraHeaders )
throws OpenIdConnectRESTHelperException {
return performQueryTokenWithPOST ( tokenUrl , null , params /*, headers*/ ) ;
return queryExchangeToken ( tokenUrl , authorization , audience , clientId , clientSecret ,
withRefreshToken | | offline ? "urn:ietf:params:oauth:token-type:refresh_token"
: "urn:ietf:params:oauth:token-type:access_token" ,
offline ? "offline_access" : null , extraHeaders ) ;
}
/ * *
* Queries from the OIDC server an UMA token , by using provided access token , for the given audience ( context ) ,
* in URLEncoded form or not , and optionally a list of permissions .
* Queries from the OIDC server an exchanged token by using provided access token , optionally for the given audience ( context )
* in URLEncoded form or not .
*
* @param tokenUrl the token endpoint { @link URL } of the OIDC server
* @param authorization the auth token ( the access token URLEncoded by the "Bearer " string )
* @param audience the audience ( context ) where to request the issuing of the ticket ( URLEncoded )
* @param permissions a list of permissions , can be < code > null < / code >
* @param audience the audience ( context ) where to request the issuing of the token ( URLEncoded or not ) , may be < code > null < / code >
* @param clientId the client id
* @param clientSecret the client secret
* @param requestedTokenType the requested token type ( e . g . < code > urn : ietf : params : oauth : token - type : refresh_token < / code > for refresh token )
* @param scope the optional scope to request ( e . g . < code > offline_access < / code > for an offline token )
* @param extraHeaders extra HTTP headers to add to the request ( e . g . < code > X - D4Science - Context < / code > custom header ) , may be < code > null < / code >
* @return the issued token
* @throws OpenIdConnectRESTHelperException if an error occurs ( also an unauthorized call ) , inspect the exception for details
* /
public static JWTToken queryUMAToken ( URL tokenUrl , String authorization , String audience ,
List < String > permissions ) throws OpenIdConnectRESTHelperException {
public static JWTToken queryExchangeToken ( URL tokenUrl , String authorization , String audience , String clientId ,
String clientSecret , String requestedTokenType , String scope , Map < String , String > extraHeaders )
throws OpenIdConnectRESTHelperException {
logger . info ( "Querying exchange token for context: " + audience ) ;
Map < String , List < String > > params = new HashMap < > ( ) ;
params . put ( "grant_type" , Arrays . asList ( "urn:ietf:params:oauth:grant-type:uma-ticket" ) ) ;
if ( audience . startsWith ( "/" ) ) {
params . put ( "subject_token" , Arrays . asList ( authorization ) ) ;
params . put ( "client_id" , Arrays . asList ( clientId ) ) ;
params . put ( "client_secret" , Arrays . asList ( clientSecret ) ) ;
params . put ( "grant_type" , Arrays . asList ( "urn:ietf:params:oauth:grant-type:token-exchange" ) ) ;
params . put ( "subject_token_type" , Arrays . asList ( "urn:ietf:params:oauth:token-type:access_token" ) ) ;
params . put ( "requested_token_type" , Arrays . asList ( requestedTokenType ) ) ;
if ( scope ! = null ) {
params . put ( "scope" , Arrays . asList ( scope ) ) ;
}
if ( audience ! = null ) {
if ( audience . startsWith ( "/" ) ) {
try {
logger . trace ( "Audience was provided in non URL encoded form, encoding it" ) ;
audience = URLEncoder . encode ( audience , "UTF-8" ) ;
} catch ( UnsupportedEncodingException e ) {
logger . error ( "Cannot URL encode 'audience'" , e ) ;
}
}
try {
logger . trace ( "Audience was provided in non URL encoded form, encoding it" ) ;
audience = URLEncoder . encode ( audience , "UTF-8" ) ;
params . put ( "audience" , Arrays . asList ( URLEncoder . encode ( audience , "UTF-8" ) ) ) ;
} catch ( UnsupportedEncodingException e ) {
logger . error ( "Cannot URL encode 'audience'" , e ) ;
}
}
try {
params . put ( "audience" , Arrays . asList ( URLEncoder . encode ( audience , "UTF-8" ) ) ) ;
} catch ( UnsupportedEncodingException e ) {
logger . error ( "Cannot URL encode 'audience'" , e ) ;
}
if ( permissions ! = null & & ! permissions . isEmpty ( ) ) {
params . put (
"permission" , permissions . stream ( ) . map ( s - > {
try {
return URLEncoder . encode ( s , "UTF-8" ) ;
} catch ( UnsupportedEncodingException e ) {
return "" ;
}
} ) . collect ( Collectors . toList ( ) ) ) ;
}
return performQueryTokenWithPOST ( tokenUrl , authorization , params ) ;
return performQueryTokenWithPOST ( tokenUrl , null , params , extraHeaders ) ;
}
/ * *
@ -322,6 +425,7 @@ public class OpenIdConnectRESTHelper {
* /
public static JWTToken refreshToken ( URL tokenURL , String clientId , JWTToken token )
throws OpenIdConnectRESTHelperException {
return refreshToken ( tokenURL , clientId , null , token ) ;
}