From 4f2d348682ae87ef57bd8ea1f56f303c1a9f1494 Mon Sep 17 00:00:00 2001 From: "lucio.lelii" Date: Thu, 21 Mar 2019 13:39:33 +0000 Subject: [PATCH] added cliend_id and clent_secret parameter passed as Basic Authorization in header to make it oauth2 compliant git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portal/oauth@178642 82a268e6-3cf1-43bd-a215-b396298e98cf --- .../gcube/portal/oauth/CredentialsBean.java | 23 ++++++++ .../org/gcube/portal/oauth/OauthService.java | 52 +++++++++++++++---- 2 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 src/main/java/org/gcube/portal/oauth/CredentialsBean.java diff --git a/src/main/java/org/gcube/portal/oauth/CredentialsBean.java b/src/main/java/org/gcube/portal/oauth/CredentialsBean.java new file mode 100644 index 0000000..2d6af5f --- /dev/null +++ b/src/main/java/org/gcube/portal/oauth/CredentialsBean.java @@ -0,0 +1,23 @@ +package org.gcube.portal.oauth; + +public class CredentialsBean { + + private String clientId; + private String clientSecret; + + public CredentialsBean(String clientId, String clientSecret) { + super(); + this.clientId = clientId; + this.clientSecret = clientSecret; + } + + public String getClientId() { + return clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + +} diff --git a/src/main/java/org/gcube/portal/oauth/OauthService.java b/src/main/java/org/gcube/portal/oauth/OauthService.java index ab79677..786654d 100644 --- a/src/main/java/org/gcube/portal/oauth/OauthService.java +++ b/src/main/java/org/gcube/portal/oauth/OauthService.java @@ -2,19 +2,23 @@ package org.gcube.portal.oauth; import static org.gcube.common.authorization.client.Constants.authorizationService; +import java.net.URLDecoder; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.inject.Singleton; +import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.FormParam; import javax.ws.rs.GET; 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.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; +import javax.xml.bind.DatatypeConverter; import org.gcube.common.authorization.library.ClientType; import org.gcube.common.authorization.library.provider.AuthorizationProvider; @@ -26,6 +30,7 @@ import org.gcube.portal.oauth.cache.CacheCleaner; import org.gcube.portal.oauth.input.PushCodeBean; import org.gcube.portal.oauth.output.AccessTokenBeanResponse; import org.gcube.portal.oauth.output.AccessTokenErrorResponse; +import org.gcube.smartgears.Constants; import org.slf4j.LoggerFactory; @@ -36,6 +41,9 @@ public class OauthService { public static final String OAUTH_TOKEN_GET_METHOD_NAME_REQUEST = "access-token"; private static final String GRANT_TYPE_VALUE = "authorization_code"; + private static final String AUTHORIZATION_HEADER = "Authorization"; + + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(OauthService.class); /** @@ -158,17 +166,29 @@ public class OauthService { @FormParam("client_secret") String clientSecret, // i.e., application token @FormParam("redirect_uri") String redirectUri, @FormParam("code") String code, - @FormParam("grant_type") String grantType // it must always be equal to "authorization_code" + @FormParam("grant_type") String grantType, // it must always be equal to "authorization_code" + @Context HttpServletRequest request ){ Status status = Status.BAD_REQUEST; logger.info("Request to exchange code for token"); - logger.info("Params are client_id = " + clientId + ", client_secret = " + clientSecret + - "*******************"+ ", redirect_uri = " +redirectUri + ", code = " + code + "*******************" + ", grant_type = " + grantType); + + try{ + CredentialsBean credentials = new CredentialsBean(clientId, clientSecret); + + if (clientId == null) + credentials = getCredentialFromBasicAuthorization(request); + else if (request.getHeader(AUTHORIZATION_HEADER)!=null) + throw new Exception("he client MUST NOT use more than one authentication method"); + + logger.info("Params are client_id = " + credentials.getClientId() + ", client_secret = " + credentials.getClientSecret() + + "*******************"+ ", redirect_uri = " +redirectUri + ", code = " + code + "*******************" + ", grant_type = " + grantType); + // check if something is missing - String errorMessage = checkRequest(clientId, clientSecret, redirectUri, code, grantType); + String errorMessage = checkRequest(credentials, redirectUri, code, grantType, request); + if(errorMessage != null){ logger.error("The request fails because of " + errorMessage); return Response.status(status).entity(new AccessTokenErrorResponse(errorMessage, null)).build(); @@ -186,6 +206,18 @@ public class OauthService { } } + private CredentialsBean getCredentialFromBasicAuthorization(HttpServletRequest request) { + String basicAuthorization = request.getHeader(AUTHORIZATION_HEADER); + String base64Credentials = basicAuthorization.substring("Basic".length()).trim(); + String credentials = new String(DatatypeConverter.parseBase64Binary(base64Credentials)); + // credentials = username:password + String[] splitCreds = credentials.split(":"); + String clientId = URLDecoder.decode(splitCreds[0]); + String clientSecret = URLDecoder.decode(splitCreds[1]); + return new CredentialsBean(clientId, clientSecret); + + } + /** * Check request parameters * @param clientId @@ -195,19 +227,19 @@ public class OauthService { * @param grantType * @return see https://tools.ietf.org/html/rfc6749#section-5.2 */ - private String checkRequest(String clientId, String clientSecret, - String redirectUri, String code, String grantType) { + private String checkRequest(CredentialsBean credentials, + String redirectUri, String code, String grantType, HttpServletRequest request) { try{ - if(clientId == null || clientSecret == null || redirectUri == null || code == null || grantType == null) + if(credentials.getClientId() == null || credentials.getClientSecret() == null || redirectUri == null || code == null || grantType == null ) return "invalid_request"; - if(clientId.isEmpty() || clientSecret.isEmpty() || redirectUri.isEmpty() || code.isEmpty() || grantType.isEmpty()) + if(credentials.getClientId().isEmpty() || credentials.getClientSecret().isEmpty() || redirectUri.isEmpty() || code.isEmpty() || grantType.isEmpty()) return "invalid_request"; - if(!checkIsapplicationTokenType(authorizationService().get(clientSecret).getClientInfo().getType())) // it is not an app token or it is not a token + if(!checkIsapplicationTokenType(authorizationService().get(credentials.getClientSecret()).getClientInfo().getType())) // it is not an app token or it is not a token return "invalid_client"; if(!entries.containsKey(code) || CacheBean.isExpired(entries.get(code))) return "invalid_grant"; CacheBean entry = entries.get(code); - if(!entry.getRedirectUri().equals(redirectUri) || !entry.getClientId().equals(clientId)) + if(!entry.getRedirectUri().equals(redirectUri) || !entry.getClientId().equals(credentials.getClientId())) return "invalid_grant"; if(!grantType.equals(GRANT_TYPE_VALUE)) return "unsupported_grant_type";