Add improvements to api application registation logic

auth-restructure
Rajitha Kumara 4 weeks ago
parent a45820e845
commit 40a5b00f80

@ -21,9 +21,13 @@ package io.entgra.device.mgt.core.apimgt.application.extension.api;
import io.entgra.device.mgt.core.apimgt.application.extension.APIManagementProviderService;
import io.entgra.device.mgt.core.apimgt.application.extension.api.util.APIUtil;
import io.entgra.device.mgt.core.apimgt.application.extension.api.util.RegistrationProfile;
import io.entgra.device.mgt.core.apimgt.application.extension.constants.ApiApplicationConstants;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.ApiApplicationProfile;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.IdnAuthenticationProfile;
import io.entgra.device.mgt.core.apimgt.application.extension.dto.ApiApplicationKey;
import io.entgra.device.mgt.core.apimgt.application.extension.exception.APIManagerException;
import io.entgra.device.mgt.core.apimgt.application.extension.exception.IdnAuthenticationException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
@ -37,6 +41,7 @@ import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import java.util.Arrays;
import java.util.HashSet;
public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegistrationService {
@ -57,15 +62,27 @@ public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegi
String msg = "Invalid tenant domain : " + tenantDomain;
return Response.status(Response.Status.NOT_ACCEPTABLE).entity(msg).build();
}
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username);
String password = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminPassword();
IdnAuthenticationProfile idnAuthenticationProfile = new IdnAuthenticationProfile();
idnAuthenticationProfile.setUsername(username);
idnAuthenticationProfile.setPassword(password);
ApiApplicationProfile apiApplicationProfile = new ApiApplicationProfile();
apiApplicationProfile.setApplicationName(applicationName);
apiApplicationProfile.setTags(APIUtil.getDefaultTags());
apiApplicationProfile.setGrantTypes("");
APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService();
ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(
applicationName, APIUtil.getDefaultTags(),
ApiApplicationConstants.DEFAULT_TOKEN_TYPE, username, false,
ApiApplicationConstants.DEFAULT_VALIDITY_PERIOD, PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminPassword(), null, null, null, false);
ApiApplicationKey apiApplicationKey =
apiManagementProviderService.registerApiApplication(idnAuthenticationProfile,
apiApplicationProfile);
return Response.status(Response.Status.CREATED).entity(apiApplicationKey.toString()).build();
} catch (APIManagerException e) {
String msg = "Error occurred while registering an application '" + applicationName + "'";
@ -79,6 +96,10 @@ public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegi
String msg = "Failed to retrieve the device service";
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} catch (IdnAuthenticationException | BadRequestException | UnexpectedResponseException e) {
String msg = "Error encountered while registering api application";
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
@ -89,61 +110,49 @@ public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegi
public Response register(RegistrationProfile registrationProfile) {
try {
if ((registrationProfile.getTags() != null && registrationProfile.getTags().length != 0)) {
if (!APIUtil.getAllowedApisTags().containsAll(Arrays.asList(registrationProfile.getTags()))) {
return Response.status(Response.Status.NOT_ACCEPTABLE).entity("APIs(Tags) are not allowed to this user."
if (!new HashSet<>(APIUtil.getAllowedApisTags()).containsAll(Arrays.asList(registrationProfile.getTags()))) {
return Response.status(Response.Status.NOT_ACCEPTABLE).entity("APIs(Tags) are not allowed to this" +
" user."
).build();
}
}
String username = APIUtil.getAuthenticatedUser();
APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService();
String validityPeriod;
if (registrationProfile.getValidityPeriod() == null) {
validityPeriod = ApiApplicationConstants.DEFAULT_VALIDITY_PERIOD;
} else {
validityPeriod = registrationProfile.getValidityPeriod();
}
String applicationName = registrationProfile.getApplicationName();
IdnAuthenticationProfile idnAuthenticationProfile = new IdnAuthenticationProfile();
idnAuthenticationProfile.setUsername(registrationProfile.getUsername());
idnAuthenticationProfile.setPassword(registrationProfile.getPassword());
if (username.equals(registrationProfile.getUsername())) {
synchronized (ApiApplicationRegistrationServiceImpl.class) {
ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(
applicationName, registrationProfile.getTags(),
ApiApplicationConstants.DEFAULT_TOKEN_TYPE, username,
registrationProfile.isAllowedToAllDomains(), validityPeriod,
registrationProfile.getPassword(), null, registrationProfile.getSupportedGrantTypes(),
registrationProfile.getCallbackUrl(), false);
return Response.status(Response.Status.CREATED).entity(apiApplicationKey.toString()).build();
}
}
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(PrivilegedCarbonContext.
getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration().getAdminUserName());
ApiApplicationProfile apiApplicationProfile = new ApiApplicationProfile();
apiApplicationProfile.setApplicationName(registrationProfile.getApplicationName());
apiApplicationProfile.setTags(registrationProfile.getTags());
apiApplicationProfile.setCallbackUrl(registrationProfile.getCallbackUrl());
apiApplicationProfile.setGrantTypes(String.join(" ", registrationProfile.getSupportedGrantTypes()));
synchronized (ApiApplicationRegistrationServiceImpl.class) {
ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(
applicationName, registrationProfile.getTags(),
ApiApplicationConstants.DEFAULT_TOKEN_TYPE, registrationProfile.getUsername(),
registrationProfile.isAllowedToAllDomains(), validityPeriod,
registrationProfile.getPassword(), null, registrationProfile.getSupportedGrantTypes(),
registrationProfile.getCallbackUrl(), false);
return Response.status(Response.Status.CREATED).entity(apiApplicationKey.toString()).build();
}
} catch (APIManagerException e) {
String msg = "Error occurred while registering an application with apis '"
+ StringUtils.join(registrationProfile.getTags(), ",") + "'";
ApiApplicationKey apiApplicationKey =
apiManagementProviderService.registerApiApplication(idnAuthenticationProfile,
apiApplicationProfile);
return Response.status(Response.Status.CREATED).entity(apiApplicationKey).build();
} catch (IdnAuthenticationException e) {
String msg = "Failed to authenticate the user " + registrationProfile.getUsername();
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("false").build();
} catch (DeviceManagementException e) {
String msg = "Failed to retrieve the device service";
return Response.status(Response.Status.UNAUTHORIZED).entity(msg).build();
} catch (BadRequestException e) {
String msg =
"Received bad request for registering api application " + registrationProfile.getApplicationName();
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
} catch (UnexpectedResponseException e) {
String msg =
"Received unexpected response when registering the api application " + registrationProfile.getApplicationName();
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} catch (UserStoreException e) {
String msg = "Failed to access user space.";
} catch (DeviceManagementException | APIManagerException e) {
String msg =
"Error occurred while registering an application " + registrationProfile.getApplicationName() +
" with apis '"
+ StringUtils.join(registrationProfile.getTags(), ",") + "'";
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
}
}

@ -0,0 +1,96 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.apimgt.application.extension.api.common;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
@Provider
@Produces(APPLICATION_JSON)
@Consumes(APPLICATION_JSON)
public class GsonMessageBodyHandler implements MessageBodyWriter<Object>, MessageBodyReader<Object> {
private Gson gson;
private static final String UTF_8 = "UTF-8";
public boolean isReadable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
return true;
}
private Gson getGson() {
if (gson == null) {
final GsonBuilder gsonBuilder = new GsonBuilder();
gson = gsonBuilder.create();
}
return gson;
}
public Object readFrom(Class<Object> objectClass, Type type, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> stringStringMultivaluedMap, InputStream entityStream)
throws IOException, WebApplicationException {
InputStreamReader reader = new InputStreamReader(entityStream, "UTF-8");
try {
return getGson().fromJson(reader, type);
} finally {
reader.close();
}
}
public boolean isWriteable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
return true;
}
public long getSize(Object o, Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
return -1;
}
public void writeTo(Object object, Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> stringObjectMultivaluedMap, OutputStream entityStream)
throws IOException, WebApplicationException {
OutputStreamWriter writer = new OutputStreamWriter(entityStream, UTF_8);
try {
getGson().toJson(object, type, writer);
} finally {
writer.close();
}
}
}

@ -31,9 +31,11 @@
</bean>
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
<ref bean="jsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
<bean id="jsonProvider" class="io.entgra.device.mgt.core.apimgt.application.extension.api.common.GsonMessageBodyHandler"/>
</beans>

@ -37,12 +37,12 @@
</servlet-mapping>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>true</param-value>
<param-value>false</param-value>
</context-param>
<!--This is to support basic auth.-->
<context-param>
<param-name>basicAuth</param-name>
<param-value>true</param-value>
<param-value>false</param-value>
</context-param>
<!--publish to apim-->
@ -59,10 +59,10 @@
<param-value>false</param-value>
</context-param>
<filter>
<filter-name>ApiPermissionFilter</filter-name>
<filter-class>io.entgra.device.mgt.core.apimgt.application.extension.api.filter.ApiPermissionFilter</filter-class>
</filter>
<!-- <filter>-->
<!-- <filter-name>ApiPermissionFilter</filter-name>-->
<!-- <filter-class>io.entgra.device.mgt.core.apimgt.application.extension.api.filter.ApiPermissionFilter</filter-class>-->
<!-- </filter>-->
<filter>
<filter-name>HttpHeaderSecurityFilter</filter-name>
@ -100,9 +100,9 @@
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ApiPermissionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- <filter-mapping>-->
<!-- <filter-name>ApiPermissionFilter</filter-name>-->
<!-- <url-pattern>/*</url-pattern>-->
<!-- </filter-mapping>-->
</web-app>

@ -46,6 +46,12 @@
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
<exclusions>
<exclusion>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
@ -88,7 +94,11 @@
<artifactId>io.entgra.device.mgt.core.device.mgt.common</artifactId>
<!-- <scope>provided</scope>-->
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
@ -122,6 +132,7 @@
<Bundle-Description>API Management Application Bundle</Bundle-Description>
<Private-Package>io.entgra.device.mgt.core.apimgt.application.extension.internal</Private-Package>
<Import-Packages>
com.google.gson.*;version="${google.gson.version}",
io.entgra.device.mgt.core.apimgt.application.extension.bean,
io.entgra.device.mgt.core.apimgt.application.extension.dto,
io.entgra.device.mgt.core.apimgt.application.extension.exception,

@ -18,46 +18,48 @@
package io.entgra.device.mgt.core.apimgt.application.extension;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.ApiApplicationProfile;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.IdnAuthenticationProfile;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.Token;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.TokenCreationProfile;
import io.entgra.device.mgt.core.apimgt.application.extension.dto.ApiApplicationKey;
import io.entgra.device.mgt.core.apimgt.application.extension.exception.APIManagerException;
import io.entgra.device.mgt.core.identity.jwt.client.extension.dto.AccessTokenInfo;
import java.util.ArrayList;
import io.entgra.device.mgt.core.apimgt.application.extension.exception.IdnAuthenticationException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
/**
* This comprise on operation that is been done with api manager from CDMF. This service needs to be implemented in APIM.
* This comprise on operation that is been done with api manager from CDMF. This service needs to be implemented in
* APIM.
*/
public interface APIManagementProviderService {
/**
* Check whether the tier is loaded for the tenant.
*
* @return
*/
boolean isTierLoaded();
ApiApplicationKey generateAndRetrieveApplicationKeys(String applicationName, String[] tags,
String keyType, String username,
boolean isAllowedAllDomains,
String validityTime,
String password, String accessToken,
ArrayList<String> supportedGrantTypes,
String callbackUrl,
boolean isMappingRequired) throws APIManagerException;
/**
* To get access token for given scopes and for the given validity period
* @param scopes Scopes
* @param tags Tags
* @param applicationName Application Name
* @param tokenType Token Type
* @param validityPeriod Validity Period
* @param username Name of the user to create the token. If null, set as carbon context user
* @return {@link String} Access Token
* @throws APIManagerException if error occurred while getting the access token for given scopes,
* validity period etc.
* Create and retrieve API application token base on {@link TokenCreationProfile}
* @param tokenCreationProfile {@link TokenCreationProfile}
* @return Retrieve {@link Token} result on a successful execution
* @throws APIManagerException Throws when error occurred while retrieving the token
*/
AccessTokenInfo getAccessToken(String scopes, String[] tags, String applicationName, String
tokenType, String validityPeriod, String username)
throws APIManagerException;
Token getToken(TokenCreationProfile tokenCreationProfile) throws APIManagerException;
/**
* Register API application base on {@link ApiApplicationProfile}
* @param idnAuthenticationProfile Application owner's authentication user details
* @param apiApplicationProfile {@link ApiApplicationProfile}
* @return {@link ApiApplicationKey} result on a successful execution
* @throws IdnAuthenticationException Throws when authentication error occurred
* @throws APIManagerException Throws when error encountered while registering the application profile
* @throws BadRequestException Throws when the application profile contains invalid attributes
* @throws UnexpectedResponseException Throws when unexpected response received from the REST API client
*/
ApiApplicationKey registerApiApplication(IdnAuthenticationProfile idnAuthenticationProfile,
ApiApplicationProfile apiApplicationProfile)
throws IdnAuthenticationException, APIManagerException, BadRequestException, UnexpectedResponseException;
}

@ -18,420 +18,319 @@
package io.entgra.device.mgt.core.apimgt.application.extension;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.APIRegistrationProfile;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.ApiApplicationProfile;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.IdnAuthenticationProfile;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.Token;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.TokenCreationProfile;
import io.entgra.device.mgt.core.apimgt.application.extension.constants.ApiApplicationConstants;
import io.entgra.device.mgt.core.apimgt.application.extension.dto.ApiApplicationKey;
import io.entgra.device.mgt.core.apimgt.application.extension.exception.APIManagerException;
import io.entgra.device.mgt.core.apimgt.application.extension.exception.IdnAuthenticationException;
import io.entgra.device.mgt.core.apimgt.application.extension.internal.APIApplicationManagerExtensionDataHolder;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.ConsumerRESTAPIServices;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.APIInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Application;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.ApplicationKey;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.KeyManager;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Subscription;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataKeyAlreadyExistsException;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.Metadata;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.MetadataManagementService;
import io.entgra.device.mgt.core.identity.jwt.client.extension.JWTClient;
import io.entgra.device.mgt.core.identity.jwt.client.extension.dto.AccessTokenInfo;
import io.entgra.device.mgt.core.identity.jwt.client.extension.exception.JWTClientException;
import io.entgra.device.mgt.core.identity.jwt.client.extension.service.JWTClientManagerService;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.ConsumerRESTAPIServices;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.ApiApplicationInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.constants.Constants;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.OAuthClientException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.Metadata;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.MetadataManagementService;
import okhttp3.Credentials;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONObject;
import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.impl.APIManagerConfiguration;
import org.wso2.carbon.apimgt.impl.APIManagerFactory;
import org.wso2.carbon.apimgt.impl.internal.ServiceReferenceHolder;
import org.wso2.carbon.apimgt.impl.utils.APIUtil;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
* This class represents an implementation of APIManagementProviderService.
*/
public class APIManagementProviderServiceImpl implements APIManagementProviderService {
private static final Log log = LogFactory.getLog(APIManagementProviderServiceImpl.class);
public static final APIManagerFactory API_MANAGER_FACTORY = APIManagerFactory.getInstance();
private static final Log log = LogFactory.getLog(APIManagementProviderServiceImpl.class);
private static final APIManagerConfiguration config =
ServiceReferenceHolder.getInstance().getAPIManagerConfigurationService().getAPIManagerConfiguration();
private static final OkHttpClient client = new OkHttpClient();
private static final String UNLIMITED_TIER = "Unlimited";
private static final String JWT_TOKEN_TYPE = "JWT";
private static final Gson gson = new Gson();
@Override
public boolean isTierLoaded() {
private static JSONObject generateRequestBody(TokenCreationProfile tokenCreationProfile) {
JSONObject requestBody = new JSONObject();
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
if ("password".equals(tokenCreationProfile.getGrantType())) {
requestBody.put("username", tokenCreationProfile.getUsername());
requestBody.put("password", tokenCreationProfile.getPassword());
}
try {
APIUtil.getTiers(APIConstants.TIER_APPLICATION_TYPE, tenantDomain);
return true;
} catch (APIManagementException e) {
log.error("APIs not ready", e);
if ("refresh_token".equals(tokenCreationProfile.getGrantType())) {
requestBody.put("refresh_token", tokenCreationProfile.getRefreshToken());
}
return false;
if ("authorization_code".equals(tokenCreationProfile.getGrantType())) {
requestBody.put("code", tokenCreationProfile.getCode());
requestBody.put("redirect_uri", tokenCreationProfile.getCallbackUrl());
}
requestBody.put("grant_type", tokenCreationProfile.getGrantType());
requestBody.put("scope", tokenCreationProfile.getScope());
return requestBody;
}
@Override
public synchronized ApiApplicationKey generateAndRetrieveApplicationKeys(String applicationName, String[] tags,
String keyType, String username,
boolean isAllowedAllDomains,
String validityTime,
String password, String accessToken,
ArrayList<String> supportedGrantTypes,
String callbackUrl,
boolean isMappingRequired)
throws APIManagerException {
ApiApplicationInfo apiApplicationInfo = new ApiApplicationInfo();
if (StringUtils.isEmpty(accessToken)) {
apiApplicationInfo = getApplicationInfo(username, password);
} else {
apiApplicationInfo.setAccess_token(accessToken);
private static ApiApplicationKey registerApiApplication(ApiApplicationProfile apiApplicationProfile)
throws APIManagerException, BadRequestException, UnexpectedResponseException {
if (apiApplicationProfile.getGrantTypes().contains("authorization_code")
&& StringUtils.isEmpty(apiApplicationProfile.getCallbackUrl())) {
throw new BadRequestException("Invalid request found.");
}
ConsumerRESTAPIServices consumerRESTAPIServices =
APIApplicationManagerExtensionDataHolder.getInstance().getConsumerRESTAPIServices();
try {
Map<String, String> headerParams = new HashMap<>();
if (!"carbon.super".equals(PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(true))) {
headerParams.put("X-WSO2-Tenant", "carbon.super");
}
List<Application> applications =
Arrays.asList(consumerRESTAPIServices.getAllApplications(apiApplicationProfile.getApplicationName()));
Map<String, APIInfo> uniqueApiSet = new HashMap<>();
if (tags != null) {
for (String tag : tags) {
Map<String, String> queryParams = new HashMap<>();
queryParams.put("tag", tag);
APIInfo[] apiInfos = consumerRESTAPIServices.getAllApis(apiApplicationInfo, queryParams, headerParams);
Arrays.stream(apiInfos).forEach(apiInfo -> uniqueApiSet.putIfAbsent(apiInfo.getName(), apiInfo));
}
if (applications.size() > 1) {
String msg = "Found more than one application with the same application name : [ " +
apiApplicationProfile.getApplicationName() + " ]";
throw new APIManagerException(msg);
}
List<APIInfo> uniqueApiList = new ArrayList<>(uniqueApiSet.values());
io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Application[] applications =
consumerRESTAPIServices.getAllApplications(apiApplicationInfo, applicationName);
if (applications.length == 0) {
return handleNewAPIApplication(applicationName, uniqueApiList, apiApplicationInfo, keyType,
validityTime, supportedGrantTypes, callbackUrl, isMappingRequired);
} else {
if (applications.length == 1) {
Optional<io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Application> applicationOpt =
Arrays.stream(applications).findFirst();
io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Application application =
applicationOpt.get();
MetadataManagementService metadataManagementService = APIApplicationManagerExtensionDataHolder.getInstance().getMetadataManagementService();
Metadata metaData = metadataManagementService.retrieveMetadata(applicationName);
if (metaData == null) {
// Todo add a comment
consumerRESTAPIServices.deleteApplication(apiApplicationInfo, application.getApplicationId());
return handleNewAPIApplication(applicationName, uniqueApiList, apiApplicationInfo, keyType,
validityTime, supportedGrantTypes, callbackUrl, isMappingRequired);
} else {
Subscription[] subscriptions = consumerRESTAPIServices.getAllSubscriptions(apiApplicationInfo, application.getApplicationId());
for (Subscription subscription : subscriptions) {
uniqueApiList.removeIf(apiInfo -> Objects.equals(apiInfo.getId(), subscription.getApiInfo().getId()));
}
if (!uniqueApiList.isEmpty()) {
addSubscriptions(application, uniqueApiList, apiApplicationInfo);
}
String[] metaValues = metaData.getMetaValue().split(":");
if (metaValues.length != 2) {
String msg = "Found invalid Meta value for meta key: " + applicationName + ". Meta Value: "
+ metaData.getMetaValue();
log.error(msg);
throw new APIManagerException(msg);
}
String applicationId = metaValues[0];
String keyMappingId = metaValues[1];
ApplicationKey applicationKey = consumerRESTAPIServices.getKeyDetails(apiApplicationInfo, applicationId, keyMappingId);
ApiApplicationKey apiApplicationKey = new ApiApplicationKey();
apiApplicationKey.setConsumerKey(applicationKey.getConsumerKey());
apiApplicationKey.setConsumerSecret(applicationKey.getConsumerSecret());
return apiApplicationKey;
}
} else {
String msg = "Found more than one application for application name: " + applicationName;
log.error(msg);
throw new APIManagerException(msg);
}
Set<APIInfo> apis = new HashSet<>();
for (String tag : apiApplicationProfile.getTags()) {
Map<String, String> queryParam = new HashMap<>();
queryParam.putIfAbsent("tag", tag);
apis.addAll(Arrays.asList(consumerRESTAPIServices.getAllApis(queryParam, new HashMap<>())));
}
return applications.isEmpty() ? createAndRetrieveApplicationKeys(apiApplicationProfile, apis) :
updateAndRetrieveApplicationKeys(applications.get(0), apiApplicationProfile, apis);
} catch (APIServicesException e) {
String msg = "Error occurred while processing the response of APIM REST endpoints.";
log.error(msg, e);
throw new APIManagerException(msg, e);
} catch (BadRequestException e) {
String msg = "Provided incorrect payload when invoking APIM REST endpoints.";
log.error(msg, e);
throw new APIManagerException(msg, e);
} catch (UnexpectedResponseException e) {
String msg = "Error occurred while invoking APIM REST endpoints.";
log.error(msg, e);
throw new APIManagerException(msg, e);
} catch (MetadataManagementException e) {
String msg = "Error occurred while getting meta data for meta key: " + applicationName;
log.error(msg, e);
throw new APIManagerException(msg, e);
throw new RuntimeException(e);
}
}
}
private ApiApplicationKey handleNewAPIApplication(String applicationName, List<APIInfo> uniqueApiList,
ApiApplicationInfo apiApplicationInfo, String keyType, String validityTime,
ArrayList<String> supportedGrantTypes, String callbackUrl,
boolean isMappingRequired) throws APIManagerException {
private static ApiApplicationKey updateAndRetrieveApplicationKeys(Application application,
ApiApplicationProfile apiApplicationProfile,
Set<APIInfo> apis)
throws BadRequestException, UnexpectedResponseException, APIServicesException, APIManagerException {
ConsumerRESTAPIServices consumerRESTAPIServices =
APIApplicationManagerExtensionDataHolder.getInstance().getConsumerRESTAPIServices();
io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Application application = new io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Application();
application.setName(applicationName);
application.setThrottlingPolicy(UNLIMITED_TIER);
try {
application = consumerRESTAPIServices.createApplication(apiApplicationInfo, application);
addSubscriptions(application, uniqueApiList, apiApplicationInfo);
KeyManager[] keyManagers = consumerRESTAPIServices.getAllKeyManagers(apiApplicationInfo);
KeyManager keyManager;
if (keyManagers.length == 1) {
keyManager = keyManagers[0];
} else {
String msg =
"Found invalid number of key managers. No of key managers found from the APIM: " + keyManagers.length;
log.error(msg);
throw new APIManagerException(msg);
List<Subscription> availableSubscriptions =
Arrays.asList(consumerRESTAPIServices.getAllSubscriptions(application.getApplicationId()));
List<Subscription> allSubscriptions = constructSubscriptionList(application.getApplicationId(), apis);
List<Subscription> newSubscriptions = new ArrayList<>();
for (Subscription subscription : allSubscriptions) {
if (!availableSubscriptions.contains(subscription)) {
newSubscriptions.add(subscription);
}
}
ApplicationKey applicationKey;
ApplicationKey[] applicationKeys = consumerRESTAPIServices.getAllKeys(application.getApplicationId());
if (applicationKeys.length == 0) {
return generateApplicationKeys(application.getApplicationId(), apiApplicationProfile.getGrantTypes(),
apiApplicationProfile.getCallbackUrl());
}
if (isMappingRequired) {
// If we need to get opaque token instead of the JWT token, we have to do the mapping. Therefore, if
// it is a requirement then we have to call the method with enabling the flag.
APIApplicationServices apiApplicationServices = APIApplicationManagerExtensionDataHolder.getInstance()
.getApiApplicationServices();
ApplicationKey applicationKey = applicationKeys[0];
APIApplicationKey apiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials(
"ClientForMapping",
"client_credentials password refresh_token urn:ietf:params:oauth:grant-type:jwt-bearer");
// Received { "code":900967,"message":"General Error" } when updating the grant types of existing application.
// Hence, as an alternative we check if there is any grant type difference and if yes simply delete the
// previous application and create a new one.
boolean isGrantsAreUpdated =
!new HashSet<>(applicationKey.getSupportedGrantTypes()).
equals(new HashSet<>(Arrays.asList(apiApplicationProfile.getGrantTypes().split(Constants.SPACE))));
apiApplicationInfo.setClientId(apiApplicationKey.getClientId());
apiApplicationInfo.setClientSecret(apiApplicationKey.getClientSecret());
if (isGrantsAreUpdated) {
consumerRESTAPIServices.deleteApplication(application.getApplicationId());
return createAndRetrieveApplicationKeys(apiApplicationProfile, apis);
}
applicationKey = consumerRESTAPIServices.mapApplicationKeys(apiApplicationInfo, application,
keyManager.getName(), keyType);
} else {
applicationKey = consumerRESTAPIServices.generateApplicationKeys(apiApplicationInfo, application.getApplicationId(),
keyManager.getName(), validityTime, keyType);
}
if (supportedGrantTypes != null || StringUtils.isNotEmpty(callbackUrl)) {
applicationKey = consumerRESTAPIServices.updateGrantType(apiApplicationInfo, application.getApplicationId(),
applicationKey.getKeyMappingId(), keyManager.getName(), supportedGrantTypes, callbackUrl);
}
if (!newSubscriptions.isEmpty()) {
consumerRESTAPIServices.createSubscriptions(newSubscriptions);
}
ApiApplicationKey apiApplicationKey = new ApiApplicationKey();
apiApplicationKey.setConsumerKey(applicationKey.getConsumerKey());
apiApplicationKey.setConsumerSecret(applicationKey.getConsumerSecret());
return new ApiApplicationKey(applicationKey.getConsumerKey(), applicationKey.getConsumerSecret());
}
Metadata metaData = new Metadata();
metaData.setMetaKey(applicationName);
String metaValue = application.getApplicationId() + ":" + applicationKey.getKeyMappingId();
metaData.setMetaValue(metaValue);
private static ApiApplicationKey createAndRetrieveApplicationKeys(ApiApplicationProfile apiApplicationProfile,
Set<APIInfo> apis)
throws BadRequestException, UnexpectedResponseException, APIServicesException, APIManagerException {
ConsumerRESTAPIServices consumerRESTAPIServices =
APIApplicationManagerExtensionDataHolder.getInstance().getConsumerRESTAPIServices();
MetadataManagementService metadataManagementService = APIApplicationManagerExtensionDataHolder.getInstance().getMetadataManagementService();
metadataManagementService.createMetadata(metaData);
return apiApplicationKey;
} catch (MetadataKeyAlreadyExistsException e) {
String msg = "Since meta key:" + applicationName + " already exists, meta data creating process failed.";
log.error(msg, e);
throw new APIManagerException(msg, e);
} catch (MetadataManagementException e) {
String msg = "Error occurred while creating meta data for meta key: " + applicationName;
log.error(msg, e);
throw new APIManagerException(msg, e);
} catch (BadRequestException e) {
String msg = "Provided incorrect payload when invoking APIM REST endpoints to handle new API application.";
log.error(msg, e);
throw new APIManagerException(msg, e);
} catch (UnexpectedResponseException e) {
String msg = "Error occurred while invoking APIM REST endpoints to handle new API application.";
log.error(msg, e);
throw new APIManagerException(msg, e);
} catch (APIServicesException e) {
String msg = "Error occurred while processing the response of APIM REST endpoints to handle new API application.";
log.error(msg, e);
throw new APIManagerException(msg, e);
}
}
Application application = new Application();
application.setName(apiApplicationProfile.getApplicationName());
application.setThrottlingPolicy(UNLIMITED_TIER);
application.setTokenType(JWT_TOKEN_TYPE);
application.setOwner(apiApplicationProfile.getOwner());
application = consumerRESTAPIServices.createApplication(application);
List<Subscription> subscriptions = constructSubscriptionList(application.getApplicationId(), apis);
/**
* This method can be used to add a new subscriptions providing the ids of the APIs and the applications.
*
* @param application {@link io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Application}
* @param apiInfos {@link List<APIInfo>}
* @param apiApplicationInfo {@link ApiApplicationInfo}
* @throws BadRequestException if incorrect data provided to call subscribing REST API.
* @throws UnexpectedResponseException if error occurred while processing the subscribing REST API.
* @throws APIServicesException if error occurred while invoking the subscribing REST API.
*/
private void addSubscriptions(
io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Application application,
List<APIInfo> apiInfos, ApiApplicationInfo apiApplicationInfo)
throws BadRequestException, UnexpectedResponseException, APIServicesException {
consumerRESTAPIServices.createSubscriptions(subscriptions);
return generateApplicationKeys(application.getApplicationId(), apiApplicationProfile.getGrantTypes(),
apiApplicationProfile.getCallbackUrl());
}
private static ApiApplicationKey generateApplicationKeys(String applicationId, String grantTypes,
String callbackUrl)
throws APIManagerException, BadRequestException, UnexpectedResponseException, APIServicesException {
ConsumerRESTAPIServices consumerRESTAPIServices =
APIApplicationManagerExtensionDataHolder.getInstance().getConsumerRESTAPIServices();
List<Subscription> subscriptionList = new ArrayList<>();
apiInfos.forEach(apiInfo -> {
KeyManager[] keyManagers = consumerRESTAPIServices.getAllKeyManagers();
if (keyManagers.length != 1) {
throw new APIManagerException("Found invalid number of key managers.");
}
ApplicationKey applicationKey = consumerRESTAPIServices.generateApplicationKeys(applicationId,
keyManagers[0].getName(), ApiApplicationConstants.DEFAULT_VALIDITY_PERIOD,
ApiApplicationConstants.DEFAULT_TOKEN_TYPE, grantTypes, callbackUrl);
return new ApiApplicationKey(applicationKey.getConsumerKey(), applicationKey.getConsumerSecret());
}
private static List<Subscription> constructSubscriptionList(String applicationId, Set<APIInfo> apiInfos) {
return apiInfos.stream().map(apiInfo -> {
Subscription subscription = new Subscription();
subscription.setApplicationId(applicationId);
subscription.setApiId(apiInfo.getId());
subscription.setApplicationId(application.getApplicationId());
subscription.setThrottlingPolicy(UNLIMITED_TIER);
subscription.setRequestedThrottlingPolicy(UNLIMITED_TIER);
subscriptionList.add(subscription);
});
consumerRESTAPIServices.createSubscriptions(apiApplicationInfo, subscriptionList);
return subscription;
}).collect(Collectors.toList());
}
@Override
public AccessTokenInfo getAccessToken(String scopes, String[] tags, String applicationName, String tokenType,
String validityPeriod, String username) throws APIManagerException {
public boolean isTierLoaded() {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
try {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(true);
ApiApplicationKey clientCredentials = getClientCredentials(tenantDomain, tags, applicationName, tokenType,
validityPeriod);
APIUtil.getTiers(APIConstants.TIER_APPLICATION_TYPE, tenantDomain);
return true;
} catch (APIManagementException e) {
log.error("APIs not ready", e);
}
if (clientCredentials == null) {
String msg = "Oauth Application creation is failed.";
log.error(msg);
throw new APIManagerException(msg);
}
return false;
}
if (username == null || username.isEmpty()) {
username =
PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername() + "@" + PrivilegedCarbonContext
.getThreadLocalCarbonContext().getTenantDomain(true);
} else {
if (!username.contains("@")) {
username += "@" + PrivilegedCarbonContext
.getThreadLocalCarbonContext().getTenantDomain(true);
}
@Override
public Token getToken(TokenCreationProfile tokenCreationProfile) throws APIManagerException {
JSONObject requestBody = generateRequestBody(tokenCreationProfile);
Request request = new Request.Builder()
.url(config.getFirstProperty(Constants.TOKE_END_POINT))
.post(RequestBody
.create(requestBody.toString(),
MediaType.parse("application/json; charset=utf-8")))
.addHeader("Authorization", Credentials.basic(tokenCreationProfile.getBasicAuthUsername(),
tokenCreationProfile.getBasicAuthPassword()))
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
return gson.fromJson(response.body() != null ? response.body().string() : null, Token.class);
}
JWTClientManagerService jwtClientManagerService = APIApplicationManagerExtensionDataHolder.getInstance()
.getJwtClientManagerService();
JWTClient jwtClient = jwtClientManagerService.getJWTClient();
String msg = "Error response [ " + response.code() + " ] received for the token acquiring request";
log.error(msg);
throw new APIManagerException(msg);
return jwtClient
.getAccessToken(clientCredentials.getConsumerKey(), clientCredentials.getConsumerSecret(), username,
scopes);
} catch (JWTClientException e) {
String msg = "JWT Error occurred while registering Application to get access token.";
log.error(msg, e);
throw new APIManagerException(msg, e);
} catch (APIManagerException e) {
String msg = "Error occurred while getting access tokens.";
log.error(msg, e);
throw new APIManagerException(msg, e);
} catch (UserStoreException e) {
String msg = "User management exception when getting client credentials.";
} catch (IOException e) {
String msg = "Error encountered while sending token acquiring request";
log.error(msg, e);
throw new APIManagerException(msg, e);
}
}
/**
* Get Client credentials of application belongs to tenant admin
*
* @param tenantDomain Tenant Domain
* @param tags Tags
* @param applicationName Application Name
* @param tokenType Token Type
* @param validityPeriod Validity Period
* @return {@link ApiApplicationKey}
* @throws APIManagerException if error occurred while generating access token
* @throws UserStoreException if error occurred while getting admin username.
*/
private ApiApplicationKey getClientCredentials(String tenantDomain, String[] tags, String applicationName,
String tokenType, String validityPeriod) throws APIManagerException, UserStoreException {
APIRegistrationProfile registrationProfile = new APIRegistrationProfile();
registrationProfile.setAllowedToAllDomains(false);
registrationProfile.setMappingAnExistingOAuthApp(false);
registrationProfile.setTags(tags);
registrationProfile.setApplicationName(applicationName);
if (tenantDomain == null || tenantDomain.isEmpty()) {
tenantDomain = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
}
@Override
public ApiApplicationKey registerApiApplication(IdnAuthenticationProfile idnAuthenticationProfile,
ApiApplicationProfile apiApplicationProfile)
throws IdnAuthenticationException, APIManagerException, BadRequestException, UnexpectedResponseException {
String flowStartingDomain = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
MetadataManagementService metadataManagementService =
APIApplicationManagerExtensionDataHolder.getInstance().getMetadataManagementService();
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(
PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration()
.getAdminUserName());
return generateAndRetrieveApplicationKeys(registrationProfile.getApplicationName(),
registrationProfile.getTags(), tokenType, PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName(),
registrationProfile.isAllowedToAllDomains(), validityPeriod, PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminPassword(), null, null, null, false);
} finally {
PrivilegedCarbonContext.endTenantFlow();
Metadata metaData =
metadataManagementService.retrieveMetadata(Constants.API_PUBLISHING_ENABLED_TENANT_LIST_KEY);
if (metaData != null) {
JsonArray tenants = gson.fromJson(metaData.getMetaValue(), JsonArray.class);
for (JsonElement tenant : tenants) {
if (Objects.equals(tenant.getAsString(), idnAuthenticationProfile.getTenantDomain())) {
flowStartingDomain = idnAuthenticationProfile.getTenantDomain();
}
}
}
} catch (MetadataManagementException metadataManagementException) {
log.warn("Failed to load API publishing enabled tenant domains from meta data registry.");
}
}
private ApiApplicationInfo getApplicationInfo(String username, String password)
throws APIManagerException {
APIApplicationServices apiApplicationServices = APIApplicationManagerExtensionDataHolder.getInstance()
.getApiApplicationServices();
if (log.isDebugEnabled()) {
log.info("Start API application registration sequences though " + flowStartingDomain + " domain.");
}
APIApplicationKey apiApplicationKey;
io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo accessTokenInfo;
try {
if (username == null || password == null) {
apiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials(
"ClientForConsumerRestCalls",
"client_credentials password refresh_token urn:ietf:params:oauth:grant-type:jwt-bearer");
} else {
apiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentialsWithUser(
"ClientForConsumerRestCalls",
username, password,
"client_credentials password refresh_token urn:ietf:params:oauth:grant-type:jwt-bearer");
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(flowStartingDomain, true);
if (APIApplicationManagerExtensionDataHolder.getInstance().getIoAuthClientService().
doAuthenticate(idnAuthenticationProfile.getUsername(), idnAuthenticationProfile.getPassword())) {
apiApplicationProfile.setOwner(idnAuthenticationProfile.getUsername());
return registerApiApplication(apiApplicationProfile);
}
accessTokenInfo = apiApplicationServices.generateAccessTokenFromRegisteredApplication(
apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
} catch (APIServicesException e) {
String errorMsg = "Error occurred while generating the API application";
log.error(errorMsg, e);
throw new APIManagerException(errorMsg, e);
}
ApiApplicationInfo applicationInfo = new ApiApplicationInfo();
applicationInfo.setClientId(apiApplicationKey.getClientId());
applicationInfo.setClientSecret(apiApplicationKey.getClientSecret());
applicationInfo.setAccess_token(accessTokenInfo.getAccess_token());
applicationInfo.setRefresh_token(accessTokenInfo.getRefresh_token());
throw new IdnAuthenticationException(
"Failed to authenticate the user : [ " + idnAuthenticationProfile.getUsername() + " ]");
return applicationInfo;
} catch (OAuthClientException e) {
String msg =
"Error encountered while performing authentication for user : [ " + idnAuthenticationProfile.getUsername() + " ]";
log.error(msg, e);
throw new APIManagerException(msg, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}

@ -0,0 +1,68 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.apimgt.application.extension.bean;
public class ApiApplicationProfile {
private String applicationName;
private String tags[];
private String callbackUrl;
private String grantTypes;
private String owner;
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public String[] getTags() {
return tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
public String getCallbackUrl() {
return callbackUrl;
}
public void setCallbackUrl(String callbackUrl) {
this.callbackUrl = callbackUrl;
}
public String getGrantTypes() {
return grantTypes;
}
public void setGrantTypes(String grantTypes) {
this.grantTypes = grantTypes;
}
}

@ -0,0 +1,58 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.apimgt.application.extension.bean;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
public class IdnAuthenticationProfile {
private String username;
private String password;
private String tenantDomain;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
String []usernameParts = this.username.split("@(?=[^@]*$)");
if (usernameParts.length == 2) {
this.tenantDomain = usernameParts[usernameParts.length - 1];
return;
}
this.tenantDomain = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTenantDomain() {
return tenantDomain;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain;
}
}

@ -0,0 +1,68 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.apimgt.application.extension.bean;
public class Token {
private long expires_in;
private String refresh_token;
private String access_token;
private String scope;
private String token_type;
public long getExpires_in() {
return expires_in;
}
public void setExpires_in(long expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getToken_type() {
return token_type;
}
public void setToken_type(String token_type) {
this.token_type = token_type;
}
}

@ -0,0 +1,104 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.apimgt.application.extension.bean;
public class TokenCreationProfile {
private String basicAuthUsername;
private String basicAuthPassword;
private String grantType;
private String scope;
private String username;
private String password;
private String callbackUrl;
private String refreshToken;
private String code;
public String getBasicAuthUsername() {
return basicAuthUsername;
}
public void setBasicAuthUsername(String basicAuthUsername) {
this.basicAuthUsername = basicAuthUsername;
}
public String getBasicAuthPassword() {
return basicAuthPassword;
}
public void setBasicAuthPassword(String basicAuthPassword) {
this.basicAuthPassword = basicAuthPassword;
}
public String getGrantType() {
return grantType;
}
public void setGrantType(String grantType) {
this.grantType = grantType;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCallbackUrl() {
return callbackUrl;
}
public void setCallbackUrl(String callbackUrl) {
this.callbackUrl = callbackUrl;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}

@ -25,29 +25,37 @@ import org.json.simple.JSONObject;
* This holds api application consumer key and secret.
*/
public class ApiApplicationKey {
private String consumerKey;
private String consumerSecret;
private String client_id;
private String client_secret;
public String getConsumerKey() {
return this.consumerKey;
public ApiApplicationKey(String client_id, String client_secret) {
this.client_id = client_id;
this.client_secret = client_secret;
}
public void setConsumerKey(String consumerKey) {
this.consumerKey = consumerKey;
public ApiApplicationKey() {
}
public String getConsumerSecret() {
return this.consumerSecret;
public String getClient_id() {
return this.client_id;
}
public void setConsumerSecret(String consumerSecret) {
this.consumerSecret = consumerSecret;
public void setClient_id(String client_id) {
this.client_id = client_id;
}
public String getClient_secret() {
return this.client_secret;
}
public void setClient_secret(String client_secret) {
this.client_secret = client_secret;
}
public String toString() {
JSONObject obj = new JSONObject();
obj.put(ApiApplicationConstants.OAUTH_CLIENT_ID, this.getConsumerKey());
obj.put(ApiApplicationConstants.OAUTH_CLIENT_SECRET, this.getConsumerSecret());
obj.put(ApiApplicationConstants.OAUTH_CLIENT_ID, this.getClient_id());
obj.put(ApiApplicationConstants.OAUTH_CLIENT_SECRET, this.getClient_secret());
return obj.toString();
}
}

@ -0,0 +1,26 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.apimgt.application.extension.exception;
public class IdnAuthenticationException extends Exception {
public IdnAuthenticationException(String msg) {
super(msg);
}
}

@ -20,6 +20,7 @@ package io.entgra.device.mgt.core.apimgt.application.extension.internal;
import io.entgra.device.mgt.core.apimgt.application.extension.APIManagementProviderService;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.ConsumerRESTAPIServices;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.IOAuthClientService;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.MetadataManagementService;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import io.entgra.device.mgt.core.identity.jwt.client.extension.service.JWTClientManagerService;
@ -41,6 +42,7 @@ public class APIApplicationManagerExtensionDataHolder {
private ConsumerRESTAPIServices consumerRESTAPIServices;
private APIApplicationServices apiApplicationServices;
private MetadataManagementService metadataManagementService;
private IOAuthClientService ioAuthClientService;
private APIApplicationManagerExtensionDataHolder() {
}
@ -134,4 +136,15 @@ public class APIApplicationManagerExtensionDataHolder {
public void setMetadataManagementService(MetadataManagementService metadataManagementService) {
this.metadataManagementService = metadataManagementService;
}
public IOAuthClientService getIoAuthClientService() {
if (ioAuthClientService == null) {
throw new IllegalStateException("Auth client service not initialized properly");
}
return ioAuthClientService;
}
public void setIoAuthClientService(IOAuthClientService ioAuthClientService) {
this.ioAuthClientService = ioAuthClientService;
}
}

@ -21,6 +21,7 @@ import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationService
import io.entgra.device.mgt.core.apimgt.extension.rest.api.ConsumerRESTAPIServices;
import io.entgra.device.mgt.core.apimgt.application.extension.APIManagementProviderService;
import io.entgra.device.mgt.core.apimgt.application.extension.APIManagementProviderServiceImpl;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.IOAuthClientService;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.MetadataManagementService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -209,4 +210,34 @@ public class APIApplicationManagerExtensionServiceComponent {
}
APIApplicationManagerExtensionDataHolder.getInstance().setMetadataManagementService(null);
}
/**
* Sets IOAuthclientService.
*
* @param ioAuthClientService An instance of {@link IOAuthClientService}
*/
@Reference(
name = "APIM.application.oauth.client.service",
service = io.entgra.device.mgt.core.apimgt.extension.rest.api.IOAuthClientService.class,
cardinality = ReferenceCardinality.MANDATORY,
policy = ReferencePolicy.DYNAMIC,
unbind = "unsetAPIApplicationServices")
protected void setIOAuthClientService(IOAuthClientService ioAuthClientService) {
if (log.isDebugEnabled()) {
log.debug("Setting IOAuthclientService.");
}
APIApplicationManagerExtensionDataHolder.getInstance().setIoAuthClientService(ioAuthClientService);
}
/**
* Unset IOAuthclientService.
*
* @param ioAuthClientService An instance of {@link IOAuthClientService}
*/
protected void unsetAPIApplicationServices(IOAuthClientService ioAuthClientService) {
if (log.isDebugEnabled()) {
log.debug("Unsetting DCR REST API Service");
}
APIApplicationManagerExtensionDataHolder.getInstance().setIoAuthClientService(null);
}
}

@ -18,7 +18,11 @@
package io.entgra.device.mgt.core.apimgt.extension.rest.api;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.*;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.APIInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Application;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.ApplicationKey;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.KeyManager;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Subscription;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.ApiApplicationInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
@ -29,44 +33,47 @@ import java.util.Map;
public interface ConsumerRESTAPIServices {
Application[] getAllApplications(ApiApplicationInfo apiApplicationInfo, String appName)
Application[] getAllApplications(String appName)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
Application getDetailsOfAnApplication(ApiApplicationInfo apiApplicationInfo, String applicationId)
Application getDetailsOfAnApplication(String applicationId)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
Application createApplication(ApiApplicationInfo apiApplicationInfo, Application application)
Application createApplication(Application application)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
Boolean deleteApplication(ApiApplicationInfo apiApplicationInfo, String applicationId)
Boolean deleteApplication(String applicationId)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
Subscription[] getAllSubscriptions(ApiApplicationInfo apiApplicationInfo, String applicationId)
Subscription[] getAllSubscriptions(String applicationId)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
APIInfo[] getAllApis(ApiApplicationInfo apiApplicationInfo, Map<String, String> queryParams, Map<String, String> headerParams)
APIInfo[] getAllApis(Map<String, String> queryParams, Map<String, String> headerParams)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
Subscription createSubscription(ApiApplicationInfo apiApplicationInfo, Subscription subscriptions)
Subscription createSubscription(Subscription subscriptions)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
Subscription[] createSubscriptions(ApiApplicationInfo apiApplicationInfo, List<Subscription> subscriptions)
public ApplicationKey[] getAllKeys(String applicationId)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
ApplicationKey generateApplicationKeys(ApiApplicationInfo apiApplicationInfo, String applicationId, String keyManager,
String validityTime, String keyType)
Subscription[] createSubscriptions(List<Subscription> subscriptions)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
ApplicationKey mapApplicationKeys(ApiApplicationInfo apiApplicationInfo, Application application, String keyManager, String keyType)
ApplicationKey generateApplicationKeys(String applicationId, String keyManager,
String validityTime, String keyType, String grantTypesToBeSupported, String callbackUrl)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
ApplicationKey getKeyDetails(ApiApplicationInfo apiApplicationInfo, String applicationId, String keyMapId)
ApplicationKey mapApplicationKeys(String consumerKey, String consumerSecret, Application application,
String keyManager, String keyType)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
ApplicationKey updateGrantType(ApiApplicationInfo apiApplicationInfo, String applicationId, String keyMapId, String keyManager,
List<String> supportedGrantTypes, String callbackUrl)
ApplicationKey getKeyDetails(String applicationId, String keyMapId)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
KeyManager[] getAllKeyManagers(ApiApplicationInfo apiApplicationInfo)
ApplicationKey updateGrantType(String applicationId, String keyMapId, List<String> supportedGrantTypes, String callbackUrl)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
KeyManager[] getAllKeyManagers()
throws APIServicesException, BadRequestException, UnexpectedResponseException;
}

@ -19,121 +19,88 @@
package io.entgra.device.mgt.core.apimgt.extension.rest.api;
import com.google.gson.Gson;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.*;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.APIInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Application;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.ApplicationKey;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.KeyManager;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Scopes;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Subscription;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.OAuthClientResponse;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.constants.Constants;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.ApiApplicationInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.OAuthClientException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.util.HttpsTrustManagerUtils;
import okhttp3.*;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.internal.APIManagerServiceDataHolder;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class ConsumerRESTAPIServicesImpl implements ConsumerRESTAPIServices {
private static final Log log = LogFactory.getLog(ConsumerRESTAPIServicesImpl.class);
private static final OkHttpClient client = new OkHttpClient(HttpsTrustManagerUtils.getSSLClient().newBuilder());
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private static final Gson gson = new Gson();
private static final String host = System.getProperty(Constants.IOT_CORE_HOST);
private static final String port = System.getProperty(Constants.IOT_CORE_HTTPS_PORT);
private static final String endPointPrefix = Constants.HTTPS_PROTOCOL + Constants.SCHEME_SEPARATOR + host
+ Constants.COLON + port;
private static final IOAuthClientService client =
APIManagerServiceDataHolder.getInstance().getIoAuthClientService();
@Override
public Application[] getAllApplications(ApiApplicationInfo apiApplicationInfo, String appName)
public Application[] getAllApplications(String appName)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String getAllApplicationsUrl = endPointPrefix + Constants.APPLICATIONS_API + "?query=" + appName;
Request.Builder builder = new Request.Builder();
builder.url(getAllApplicationsUrl);
builder.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ apiApplicationInfo.getAccess_token());
builder.get();
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
JSONArray applicationList = (JSONArray) new JSONObject(response.body().string()).get("list");
return gson.fromJson(applicationList.toString(), Application[].class);
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(apiApplicationInfo.getRefresh_token(),
apiApplicationInfo.getClientId(), apiApplicationInfo.getClientSecret());
ApiApplicationInfo refreshedApiApplicationInfo = returnApplicationInfo(apiApplicationInfo, refreshedAccessToken);
return getAllApplications(refreshedApiApplicationInfo, appName);
//TODO: max attempt count
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
OAuthClientResponse response = client.execute(request);
JSONArray applicationList = (JSONArray) new JSONObject(response.getBody()).get("list");
return gson.fromJson(applicationList.toString(), Application[].class);
} catch (OAuthClientException e) {
String msg = "Error occurred while retrieving applications for application name : [ " + appName + " ]";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
@Override
public Application getDetailsOfAnApplication(ApiApplicationInfo apiApplicationInfo, String applicationId)
public Application getDetailsOfAnApplication(String applicationId)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String getDetailsOfAPPUrl = endPointPrefix + Constants.APPLICATIONS_API + Constants.SLASH + applicationId;
Request.Builder builder = new Request.Builder();
builder.url(getDetailsOfAPPUrl);
builder.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ apiApplicationInfo.getAccess_token());
builder.get();
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
return gson.fromJson(response.body().string(), Application.class);
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(apiApplicationInfo.getRefresh_token(),
apiApplicationInfo.getClientId(), apiApplicationInfo.getClientSecret());
ApiApplicationInfo refreshedApiApplicationInfo = returnApplicationInfo(apiApplicationInfo, refreshedAccessToken);
return getDetailsOfAnApplication(refreshedApiApplicationInfo, applicationId);
//TODO: max attempt count
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
OAuthClientResponse response = client.execute(request);
return gson.fromJson(response.getBody(), Application.class);
} catch (OAuthClientException e) {
String msg = "Error occurred while retrieving details of application ID : [ " + applicationId + " ]";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
@Override
public Application createApplication(ApiApplicationInfo apiApplicationInfo, Application application)
public Application createApplication(Application application)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String getAllScopesUrl = endPointPrefix + Constants.APPLICATIONS_API;
JSONArray groups = new JSONArray();
@ -161,123 +128,68 @@ public class ConsumerRESTAPIServicesImpl implements ConsumerRESTAPIServices {
Request.Builder builder = new Request.Builder();
builder.url(getAllScopesUrl);
builder.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ apiApplicationInfo.getAccess_token());
builder.post(requestBody);
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_CREATED == response.code()) {
return gson.fromJson(response.body().string(), Application.class);
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(apiApplicationInfo.getRefresh_token(),
apiApplicationInfo.getClientId(), apiApplicationInfo.getClientSecret());
ApiApplicationInfo refreshedApiApplicationInfo = returnApplicationInfo(apiApplicationInfo, refreshedAccessToken);
return createApplication(refreshedApiApplicationInfo, application);
//TODO: max attempt count
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request body";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
OAuthClientResponse response = client.execute(request);
return gson.fromJson(response.getBody(), Application.class);
} catch (OAuthClientException e) {
String msg = "Error occurred while creating application : [ " + application.getName() + " ]";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
@Override
public Boolean deleteApplication(ApiApplicationInfo apiApplicationInfo, String applicationId)
public Boolean deleteApplication(String applicationId)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String deleteScopesUrl = endPointPrefix + Constants.APPLICATIONS_API + Constants.SLASH + applicationId;
Request.Builder builder = new Request.Builder();
builder.url(deleteScopesUrl);
builder.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ apiApplicationInfo.getAccess_token());
builder.delete();
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
return true;
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(apiApplicationInfo.getRefresh_token(),
apiApplicationInfo.getClientId(), apiApplicationInfo.getClientSecret());
ApiApplicationInfo refreshedApiApplicationInfo = returnApplicationInfo(apiApplicationInfo, refreshedAccessToken);
return deleteApplication(refreshedApiApplicationInfo, applicationId);
//TODO: max attempt count
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request body";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
OAuthClientResponse response = client.execute(request);
return HttpStatus.SC_OK == response.getCode();
} catch (OAuthClientException e) {
String msg =
"Error occurred while deleting application associated with application ID : [ " + applicationId + "]";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
@Override
public Subscription[] getAllSubscriptions(ApiApplicationInfo apiApplicationInfo, String applicationId)
public Subscription[] getAllSubscriptions(String applicationId)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String getAllScopesUrl = endPointPrefix + Constants.SUBSCRIPTION_API + "?applicationId=" + applicationId + "&limit=1000";
String getAllScopesUrl = endPointPrefix + Constants.SUBSCRIPTION_API + "?applicationId=" + applicationId +
"&limit=1000";
Request.Builder builder = new Request.Builder();
builder.url(getAllScopesUrl);
builder.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ apiApplicationInfo.getAccess_token());
builder.get();
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
JSONArray subscriptionList = (JSONArray) new JSONObject(response.body().string()).get("list");
return gson.fromJson(subscriptionList.toString(), Subscription[].class);
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(apiApplicationInfo.getRefresh_token(),
apiApplicationInfo.getClientId(), apiApplicationInfo.getClientSecret());
ApiApplicationInfo refreshedApiApplicationInfo = returnApplicationInfo(apiApplicationInfo, refreshedAccessToken);
return getAllSubscriptions(refreshedApiApplicationInfo, applicationId);
//TODO: max attempt count
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
OAuthClientResponse response = client.execute(request);
JSONArray subscriptionList = (JSONArray) new JSONObject(response.getBody()).get("list");
return gson.fromJson(subscriptionList.toString(), Subscription[].class);
} catch (OAuthClientException e) {
String msg =
"Error occurred while retrieving all subscription of application associated with application ID :" +
" [ " + applicationId + " ]";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
@Override
public APIInfo[] getAllApis(ApiApplicationInfo apiApplicationInfo, Map<String, String> queryParams, Map<String, String> headerParams)
public APIInfo[] getAllApis(Map<String, String> queryParams, Map<String, String> headerParams)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
StringBuilder getAPIsURL = new StringBuilder(endPointPrefix + Constants.DEV_PORTAL_API);
for (Map.Entry<String, String> query : queryParams.entrySet()) {
@ -286,8 +198,6 @@ public class ConsumerRESTAPIServicesImpl implements ConsumerRESTAPIServices {
Request.Builder builder = new Request.Builder();
builder.url(getAPIsURL.toString());
builder.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ apiApplicationInfo.getAccess_token());
for (Map.Entry<String, String> header : headerParams.entrySet()) {
builder.addHeader(header.getKey(), header.getValue());
@ -296,86 +206,48 @@ public class ConsumerRESTAPIServicesImpl implements ConsumerRESTAPIServices {
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
JSONArray apiList = (JSONArray) new JSONObject(response.body().string()).get("list");
return gson.fromJson(apiList.toString(), APIInfo[].class);
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(apiApplicationInfo.getRefresh_token(),
apiApplicationInfo.getClientId(), apiApplicationInfo.getClientSecret());
ApiApplicationInfo refreshedApiApplicationInfo = returnApplicationInfo(apiApplicationInfo, refreshedAccessToken);
return getAllApis(refreshedApiApplicationInfo, queryParams, headerParams);
//TODO: max attempt count
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
OAuthClientResponse response = client.execute(request);
JSONArray apiList = (JSONArray) new JSONObject(response.getBody()).get("list");
return gson.fromJson(apiList.toString(), APIInfo[].class);
} catch (OAuthClientException e) {
String msg = "Error occurred while retrieving all APIs";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
@Override
public Subscription createSubscription(ApiApplicationInfo apiApplicationInfo, Subscription subscriptions)
public Subscription createSubscription(Subscription subscription)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String createSubscriptionUrl = endPointPrefix + Constants.SUBSCRIPTION_API;
JSONObject subscriptionObject = new JSONObject();
subscriptionObject.put("applicationId", subscriptions.getApplicationId());
subscriptionObject.put("apiId", subscriptions.getApiId());
subscriptionObject.put("throttlingPolicy", subscriptions.getThrottlingPolicy());
subscriptionObject.put("requestedThrottlingPolicy", subscriptions.getRequestedThrottlingPolicy());
subscriptionObject.put("applicationId", subscription.getApplicationId());
subscriptionObject.put("apiId", subscription.getApiId());
subscriptionObject.put("throttlingPolicy", subscription.getThrottlingPolicy());
subscriptionObject.put("requestedThrottlingPolicy", subscription.getRequestedThrottlingPolicy());
RequestBody requestBody = RequestBody.create(JSON, subscriptionObject.toString());
Request.Builder builder = new Request.Builder();
builder.url(createSubscriptionUrl);
builder.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ apiApplicationInfo.getAccess_token());
builder.post(requestBody);
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_CREATED == response.code()) {
return gson.fromJson(response.body().string(), Subscription.class);
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(apiApplicationInfo.getRefresh_token(),
apiApplicationInfo.getClientId(), apiApplicationInfo.getClientSecret());
ApiApplicationInfo refreshedApiApplicationInfo = returnApplicationInfo(apiApplicationInfo, refreshedAccessToken);
return createSubscription(refreshedApiApplicationInfo, subscriptions);
//TODO: max attempt count
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request body";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
OAuthClientResponse response = client.execute(request);
return gson.fromJson(response.getBody(), Subscription.class);
} catch (OAuthClientException e) {
String msg = "Error occurred while adding subscription : [ " + subscription.getSubscriptionId() + " ] for" +
" application associated with application ID : [ " + subscription.getApplicationId() + " ]";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
@Override
public Subscription[] createSubscriptions(ApiApplicationInfo apiApplicationInfo, List<Subscription> subscriptions)
public Subscription[] createSubscriptions(List<Subscription> subscriptions)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String createSubscriptionsUrl = endPointPrefix + Constants.SUBSCRIPTION_API + "/multiple";
String subscriptionsList = gson.toJson(subscriptions);
@ -383,109 +255,64 @@ public class ConsumerRESTAPIServicesImpl implements ConsumerRESTAPIServices {
Request.Builder builder = new Request.Builder();
builder.url(createSubscriptionsUrl);
builder.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ apiApplicationInfo.getAccess_token());
builder.post(requestBody);
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
return gson.fromJson(response.body().string(), Subscription[].class);
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(apiApplicationInfo.getRefresh_token(),
apiApplicationInfo.getClientId(), apiApplicationInfo.getClientSecret());
ApiApplicationInfo refreshedApiApplicationInfo = returnApplicationInfo(apiApplicationInfo, refreshedAccessToken);
return createSubscriptions(refreshedApiApplicationInfo, subscriptions);
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request body";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
OAuthClientResponse response = client.execute(request);
return gson.fromJson(response.getBody(), Subscription[].class);
} catch (OAuthClientException e) {
String msg = "Error occurred while adding subscriptions";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
@Override
public ApplicationKey generateApplicationKeys(ApiApplicationInfo apiApplicationInfo, String applicationId, String keyManager,
String validityTime, String keyType)
public ApplicationKey generateApplicationKeys(String applicationId, String keyManager, String validityTime,
String keyType, String grantTypesToBeSupported, String callbackUrl)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String generateApplicationKeysUrl = endPointPrefix + Constants.APPLICATIONS_API + Constants.SLASH +
applicationId + "/generate-keys";
JSONArray grantTypesToBeSupported = new JSONArray();
grantTypesToBeSupported.put("password");
grantTypesToBeSupported.put("client_credentials");
JSONArray scopes = new JSONArray();
scopes.put("am_application_scope");
scopes.put("default");
JSONObject keyInfo = new JSONObject();
keyInfo.put("keyType", keyType);
keyInfo.put("keyManager", keyManager);
keyInfo.put("grantTypesToBeSupported", grantTypesToBeSupported);
keyInfo.put("callbackUrl", "");
keyInfo.put("scopes", scopes);
keyInfo.put("validityTime", 3600);
keyInfo.put("additionalProperties", new JSONObject());
keyInfo.put("grantTypesToBeSupported", grantTypesToBeSupported.split(Constants.SPACE));
if (!StringUtils.isEmpty(callbackUrl)) {
keyInfo.put("callbackUrl", callbackUrl);
}
keyInfo.put("validityTime", validityTime);
RequestBody requestBody = RequestBody.create(JSON, keyInfo.toString());
Request.Builder builder = new Request.Builder();
builder.url(generateApplicationKeysUrl);
builder.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ apiApplicationInfo.getAccess_token());
builder.post(requestBody);
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
return gson.fromJson(response.body().string(), ApplicationKey.class);
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(apiApplicationInfo.getRefresh_token(),
apiApplicationInfo.getClientId(), apiApplicationInfo.getClientSecret());
ApiApplicationInfo refreshedApiApplicationInfo = returnApplicationInfo(apiApplicationInfo, refreshedAccessToken);
return generateApplicationKeys(refreshedApiApplicationInfo, applicationId, keyManager, validityTime, keyType);
//TODO: max attempt count
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request body";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
OAuthClientResponse response = client.execute(request);
return gson.fromJson(response.getBody(), ApplicationKey.class);
} catch (OAuthClientException e) {
String msg = "Error occurred while generating application keys for application associated with " +
"application ID : [ " + applicationId + " ]";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
@Override
public ApplicationKey mapApplicationKeys(ApiApplicationInfo apiApplicationInfo, Application application, String keyManager, String keyType)
public ApplicationKey mapApplicationKeys(String consumerKey, String consumerSecret, Application application,
String keyManager, String keyType)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String getAllScopesUrl = endPointPrefix + Constants.APPLICATIONS_API + Constants.SLASH +
application.getApplicationId() + "/map-keys";
JSONObject payload = new JSONObject();
payload.put("consumerKey", apiApplicationInfo.getClientId());
payload.put("consumerSecret", apiApplicationInfo.getClientSecret());
payload.put("consumerKey", consumerKey);
payload.put("consumerSecret", consumerSecret);
payload.put("keyManager", keyManager);
payload.put("keyType", keyType);
@ -493,101 +320,76 @@ public class ConsumerRESTAPIServicesImpl implements ConsumerRESTAPIServices {
Request.Builder builder = new Request.Builder();
builder.url(getAllScopesUrl);
builder.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ apiApplicationInfo.getAccess_token());
builder.post(requestBody);
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
return gson.fromJson(response.body().string(), ApplicationKey.class);
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(apiApplicationInfo.getRefresh_token(),
apiApplicationInfo.getClientId(), apiApplicationInfo.getClientSecret());
ApiApplicationInfo refreshedApiApplicationInfo = returnApplicationInfo(apiApplicationInfo, refreshedAccessToken);
return mapApplicationKeys(refreshedApiApplicationInfo, application, keyManager, keyType);
//TODO: max attempt count
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request body";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
OAuthClientResponse response = client.execute(request);
return gson.fromJson(response.getBody(), ApplicationKey.class);
} catch (OAuthClientException e) {
String msg = "Error occurred while mapping application keys";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
@Override
public ApplicationKey getKeyDetails(ApiApplicationInfo apiApplicationInfo, String applicationId, String keyMapId)
public ApplicationKey getKeyDetails(String applicationId, String keyMapId)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String getKeyDetails = endPointPrefix + Constants.APPLICATIONS_API + Constants.SLASH + applicationId + "/oauth-keys/" + keyMapId;
String getKeyDetails = endPointPrefix + Constants.APPLICATIONS_API + Constants.SLASH + applicationId +
"/oauth-keys/" + keyMapId;
Request.Builder builder = new Request.Builder();
builder.url(getKeyDetails);
builder.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ apiApplicationInfo.getAccess_token());
builder.get();
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
return gson.fromJson(response.body().string(), ApplicationKey.class);
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(apiApplicationInfo.getRefresh_token(),
apiApplicationInfo.getClientId(), apiApplicationInfo.getClientSecret());
ApiApplicationInfo refreshedApiApplicationInfo = returnApplicationInfo(apiApplicationInfo, refreshedAccessToken);
return getKeyDetails(refreshedApiApplicationInfo, applicationId, keyMapId);
//TODO: max attempt count
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
OAuthClientResponse response = client.execute(request);
return gson.fromJson(response.getBody(), ApplicationKey.class);
} catch (OAuthClientException e) {
String msg =
"Error occurred while retrieving key details of application associated with application ID : [ " + applicationId + " ]";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
@Override
public ApplicationKey updateGrantType(ApiApplicationInfo apiApplicationInfo, String applicationId, String keyMapId, String keyManager,
List<String> supportedGrantTypes, String callbackUrl)
public ApplicationKey[] getAllKeys(String applicationId)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String getKeyDetails = endPointPrefix + Constants.APPLICATIONS_API + Constants.SLASH + applicationId + "/oauth-keys/" + keyMapId;
String getKeyDetails = endPointPrefix + Constants.APPLICATIONS_API + Constants.SLASH + applicationId +
"/oauth-keys";
Request.Builder builder = new Request.Builder();
builder.url(getKeyDetails);
builder.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ apiApplicationInfo.getAccess_token());
builder.get();
Request request = builder.build();
JSONArray supportedGrantTypeList = new JSONArray();
for (String string : supportedGrantTypes) {
supportedGrantTypeList.put(string);
try {
OAuthClientResponse response = client.execute(request);
JSONArray keyList = (JSONArray) new JSONObject(response.getBody()).get("list");
return gson.fromJson(keyList.toString(), ApplicationKey[].class);
} catch (OAuthClientException e) {
String msg =
"Error occurred while retrieving key details of application associated with application ID : [ " + applicationId + " ]";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
@Override
public ApplicationKey updateGrantType(String applicationId, String keyMapId, List<String> supportedGrantTypes, String callbackUrl)
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String getKeyDetails = endPointPrefix + Constants.APPLICATIONS_API + Constants.SLASH + applicationId +
"/oauth-keys/" + keyMapId;
Request.Builder builder = new Request.Builder();
builder.url(getKeyDetails);
JSONObject payload = new JSONObject();
payload.put("keyMappingId", keyMapId);
payload.put("keyManager", keyManager);
payload.put("supportedGrantTypes", supportedGrantTypeList);
payload.put("supportedGrantTypes", supportedGrantTypes);
payload.put("callbackUrl", (callbackUrl != null ? callbackUrl : ""));
payload.put("additionalProperties", new JSONObject());
RequestBody requestBody = RequestBody.create(JSON, payload.toString());
@ -595,80 +397,34 @@ public class ConsumerRESTAPIServicesImpl implements ConsumerRESTAPIServices {
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
return gson.fromJson(response.body().string(), ApplicationKey.class);
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(apiApplicationInfo.getRefresh_token(),
apiApplicationInfo.getClientId(), apiApplicationInfo.getClientSecret());
ApiApplicationInfo refreshedApiApplicationInfo = returnApplicationInfo(apiApplicationInfo, refreshedAccessToken);
return updateGrantType(refreshedApiApplicationInfo, applicationId, keyMapId, keyManager, supportedGrantTypes, callbackUrl);
//TODO: max attempt count
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
OAuthClientResponse response = client.execute(request);
return gson.fromJson(response.getBody(), ApplicationKey.class);
} catch (OAuthClientException e) {
String msg = "Error occurred while updating the grant types of the application associated with " +
"application ID : [ " + applicationId + " ]";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
@Override
public KeyManager[] getAllKeyManagers(ApiApplicationInfo apiApplicationInfo)
public KeyManager[] getAllKeyManagers()
throws APIServicesException, BadRequestException, UnexpectedResponseException {
String getAllKeyManagersUrl = endPointPrefix + Constants.KEY_MANAGERS_API;
Request.Builder builder = new Request.Builder();
builder.url(getAllKeyManagersUrl);
builder.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Constants.AUTHORIZATION_HEADER_PREFIX_BEARER
+ apiApplicationInfo.getAccess_token());
builder.get();
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
if (HttpStatus.SC_OK == response.code()) {
JSONArray keyManagerList = (JSONArray) new JSONObject(response.body().string()).get("list");
return gson.fromJson(keyManagerList.toString(), KeyManager[].class);
} else if (HttpStatus.SC_UNAUTHORIZED == response.code()) {
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
AccessTokenInfo refreshedAccessToken = apiApplicationServices.
generateAccessTokenFromRefreshToken(apiApplicationInfo.getRefresh_token(),
apiApplicationInfo.getClientId(), apiApplicationInfo.getClientSecret());
ApiApplicationInfo refreshedApiApplicationInfo = returnApplicationInfo(apiApplicationInfo, refreshedAccessToken);
return getAllKeyManagers(refreshedApiApplicationInfo);
//TODO: max attempt count
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg = "Bad Request, Invalid request";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg = "Response : " + response.code() + response.body();
throw new UnexpectedResponseException(msg);
}
} catch (IOException e) {
String msg = "Error occurred while processing the response";
OAuthClientResponse response = client.execute(request);
JSONArray keyManagerList = (JSONArray) new JSONObject(response.getBody()).get("list");
return gson.fromJson(keyManagerList.toString(), KeyManager[].class);
} catch (OAuthClientException e) {
String msg = "Error occurred while retrieving all key managers";
log.error(msg, e);
throw new APIServicesException(msg, e);
}
}
private ApiApplicationInfo returnApplicationInfo(ApiApplicationInfo apiApplicationInfo, AccessTokenInfo refreshedToken) {
ApiApplicationInfo applicationInfo = new ApiApplicationInfo();
applicationInfo.setClientId(apiApplicationInfo.getClientId());
applicationInfo.setClientSecret(apiApplicationInfo.getClientSecret());
applicationInfo.setAccess_token(refreshedToken.getAccess_token());
applicationInfo.setRefresh_token(refreshedToken.getRefresh_token());
return applicationInfo;
}
}

@ -0,0 +1,51 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.OAuthClientResponse;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.OAuthClientException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
import okhttp3.Request;
public interface IOAuthClientService {
/**
* Handle execution of a APIM REST services invocation request. Token and cache handling will be handled by the
* service itself.
*
* @param request Instance of {@link Request} to execute
* @return Instance of {@link OAuthClientResponse} when successful invocation happens
* @throws OAuthClientException Throws when error encountered while sending the request
* @throws BadRequestException Throws when received of an invalid request
* @throws UnexpectedResponseException Throws when unexpected response received
*/
OAuthClientResponse execute(Request request) throws OAuthClientException, BadRequestException,
UnexpectedResponseException;
/**
* Use to authenticate user against Identify Server
*
* @param username Username of the user
* @param password Password of the User
* @return Returns true if the requested user is authenticated user, otherwise false
* @throws OAuthClientException Throws when error encountered while authenticating
*/
boolean doAuthenticate(String username, String password) throws OAuthClientException;
}

@ -0,0 +1,471 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.OAuthClientResponse;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.constants.Constants;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.OAuthClientException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.util.HttpsTrustManagerUtils;
import okhttp3.Credentials;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONObject;
import org.wso2.carbon.apimgt.impl.APIManagerConfiguration;
import org.wso2.carbon.apimgt.impl.internal.ServiceReferenceHolder;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class OAuthClient implements IOAuthClientService {
private static final Log log = LogFactory.getLog(OAuthClient.class);
private static final OkHttpClient client = new OkHttpClient(HttpsTrustManagerUtils.getSSLClient().newBuilder());
private static final Gson gson = new Gson();
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private static final String IDN_DCR_CLIENT_PREFIX = "_REST_API_INVOKER_SERVICE";
private static final String IDN_REST_API_INVOKER_USER = "rest_service_reserved_user";
private static final String IDN_REST_API_INVOKER_USER_PWD = "rest_service_reserved_user";
private static final APIManagerConfiguration config =
ServiceReferenceHolder.getInstance().getAPIManagerConfigurationService().getAPIManagerConfiguration();
private static final String tokenEndpoint = config.getFirstProperty(Constants.TOKE_END_POINT);
private static final String dcrEndpoint = config.getFirstProperty(Constants.DCR_END_POINT);
private static final Map<String, CacheWrapper> cache = new ConcurrentHashMap<>();
private static final int MAX_RETRY_ATTEMPT = 2;
private OAuthClient() {
}
public static OAuthClient getInstance() {
return OAuthClientHolder.INSTANCE;
}
/**
* Handle execution of a APIM REST services invocation request. Token and cache handling will be handled by the
* service itself.
*
* @param request Instance of {@link Request} to execute
* @return Instance of {@link OAuthClientResponse} when successful invocation happens
* @throws OAuthClientException {@link OAuthClientException}
* @throws BadRequestException {@link BadRequestException}
* @throws UnexpectedResponseException {@link UnexpectedResponseException}
*/
@Override
public OAuthClientResponse execute(Request request) throws OAuthClientException, BadRequestException,
UnexpectedResponseException {
int currentRetryAttempt = 0;
OAuthClientResponse oAuthClientResponse;
while (true) {
try {
request = intercept(request);
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
oAuthClientResponse = mapToOAuthClientResponse(response);
break;
}
if (response.code() == HttpStatus.SC_NOT_FOUND) {
if (log.isDebugEnabled()) {
log.info("Resource not found for the request [ " + request.url() + " ]");
}
oAuthClientResponse = mapToOAuthClientResponse(response);
break;
}
// entering to the retrying phase, so increment the counter
currentRetryAttempt++;
if (response.code() == HttpStatus.SC_UNAUTHORIZED) {
if (currentRetryAttempt <= MAX_RETRY_ATTEMPT) {
refresh();
} else {
String msg =
"Request [ " + request.url() + " ] failed with code : [ " + response.code() + " ]" +
" & body : [ " + (response.body() != null ?
response.body().string() : " empty body received!") + " ]";
log.error(msg);
throw new UnexpectedResponseException(msg);
}
} else if (HttpStatus.SC_BAD_REQUEST == response.code()) {
String msg =
"Encountered a bad request! Request [ " + request.url() + " ] failed with code : " +
"[ " + response.code() + " ] & body : [ " + (response.body() != null ?
response.body().string() : " empty body received!") + " ]";
log.error(msg);
throw new BadRequestException(msg);
} else {
String msg =
"Request [ " + request.url() + " ]failed with code : [ " + response.code() + " ] & " +
"body : [ " + (response.body() != null ? response.body().string() : " empty " +
"body received!") + " ]";
log.error(msg);
throw new UnexpectedResponseException(msg);
}
}
} catch (IOException ex) {
String msg =
"Error occurred while executing the request : [ " + request.method() + ":" + request.url() +
" ]";
throw new OAuthClientException(msg, ex);
}
}
return oAuthClientResponse;
}
@Override
public boolean doAuthenticate(String username, String password) throws OAuthClientException {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
CacheWrapper cacheWrapper = cache.computeIfAbsent(tenantDomain, key -> {
CacheWrapper constructedWrapper = null;
try {
Keys keys = idnDynamicClientRegistration();
Tokens tokens = idnTokenGeneration(keys);
constructedWrapper = new CacheWrapper(keys, tokens);
} catch (Exception e) {
log.error("Error encountered while updating the cache", e);
}
return constructedWrapper;
});
if (cacheWrapper != null) {
String tokenRequestJsonStr = (new JSONObject())
.put("grant_type", Constants.PASSWORD_GRANT_TYPE)
.put("username", username)
.put("password", password)
.put("scope", Constants.SCOPES)
.put("callbackUrl", Constants.PLACEHOLDING_CALLBACK_URL)
.toString();
RequestBody requestBody = RequestBody.Companion.create(tokenRequestJsonStr, JSON);
Request tokenRequest = new Request.Builder()
.url(tokenEndpoint)
.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Credentials.basic(cacheWrapper.keys.consumerKey,
cacheWrapper.keys.consumerSecret))
.post(requestBody)
.build();
try (Response response = client.newCall(tokenRequest).execute()) {
if (response.isSuccessful()) {
Tokens tokens = mapTokens(response.body());
if (tokens.accessToken != null) {
if (log.isDebugEnabled()) {
log.info("IDN authentication success for user : [ " + username + " ]");
}
return true;
}
}
} catch (IOException e) {
String msg =
"Error encountered while performing IDN authentication for received user : [ " + username +
" ]";
log.error(msg, e);
throw new OAuthClientException(msg, e);
}
}
if (log.isDebugEnabled()) {
log.info("IDN authentication failed for user : [ " + username + " ]");
}
return false;
}
/**
* Dynamic client registration will be handled through here. These clients can be located under carbon console's
* service provider section in respective tenants.
*
* @return Instance of {@link Keys} containing the dcr client's credentials
* @throws IOException Throws when error encountered while executing dcr request
* @throws OAuthClientException Throws when failed to register dcr client
*/
private Keys idnDynamicClientRegistration() throws IOException, OAuthClientException {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
createRestClientInvokerUserIfNotExists(tenantDomain);
String tenantAwareClientName = tenantDomain.toUpperCase() + IDN_DCR_CLIENT_PREFIX;
List<String> grantTypes = Arrays.asList(Constants.PASSWORD_GRANT_TYPE, Constants.REFRESH_TOKEN_GRANT_TYPE);
String dcrRequestJsonStr = (new JSONObject())
.put("clientName", tenantAwareClientName)
.put("owner", IDN_REST_API_INVOKER_USER + "@" + tenantDomain)
.put("saasApp", true)
.put("grantType", String.join(Constants.SPACE, grantTypes))
.put("tokenType", "Default")
.toString();
RequestBody requestBody = RequestBody.Companion.create(dcrRequestJsonStr, JSON);
Request dcrRequest = new Request.Builder()
.url(dcrEndpoint)
.addHeader(Constants.AUTHORIZATION_HEADER_NAME,
Credentials.basic(IDN_REST_API_INVOKER_USER + "@" + tenantDomain
, IDN_REST_API_INVOKER_USER_PWD))
.post(requestBody)
.build();
try (Response response = client.newCall(dcrRequest).execute()) {
if (response.isSuccessful()) {
return mapKeys(response.body());
}
}
String msg = "Error encountered while processing DCR request. Tried client : [ " + tenantAwareClientName + " ]";
log.error(msg);
throw new OAuthClientException(msg);
}
/**
* Token obtaining procedure will be handled here. Since the required permissions for invoking the APIM REST
* services are available for the tenant admins, this procedure will use admin credentials for obtaining tokens.
* Also, please note that these tokens are only use for invoking APIM REST services only. The password grant uses
* since it facilitates the use of refresh token.
*
* @param keys Dcr client credentials to obtain a token
* @return Instance of {@link Tokens} containing the tokens
* @throws IOException Throws when error encountered while executing token request
* @throws OAuthClientException Throws when failed to obtain tokens
*/
private Tokens idnTokenGeneration(Keys keys) throws IOException, OAuthClientException {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String tokenRequestJsonStr = (new JSONObject())
.put("grant_type", Constants.PASSWORD_GRANT_TYPE)
.put("username", IDN_REST_API_INVOKER_USER + "@" + tenantDomain)
.put("password", IDN_REST_API_INVOKER_USER_PWD)
.put("scope", Constants.SCOPES)
.put("callbackUrl", Constants.PLACEHOLDING_CALLBACK_URL)
.toString();
RequestBody requestBody = RequestBody.Companion.create(tokenRequestJsonStr, JSON);
Request tokenRequest = new Request.Builder()
.url(tokenEndpoint)
.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Credentials.basic(keys.consumerKey,
keys.consumerSecret))
.post(requestBody)
.build();
try (Response response = client.newCall(tokenRequest).execute()) {
if (response.isSuccessful()) {
return mapTokens(response.body());
}
}
String msg = "Error encountered while processing token registration request";
log.error(msg);
throw new OAuthClientException(msg);
}
/**
* Obtain and refresh idn auth tokens. Note that in the first try it try to obtain new tokens via refresh_token
* grant type, if it fails it tries to obtain new tokens via password grant type.
*
* @param keys Instance of {@link Keys} containing the dcr client's credentials
* @param refreshToken Refresh token
* @return Instance of {@link Tokens} containing the tokens
* @throws IOException Throws when error encountered while executing token request
* @throws OAuthClientException Throws when failed to obtain tokens
*/
private Tokens idnTokenRefresh(Keys keys, String refreshToken) throws IOException,
OAuthClientException {
String tokenRequestJsonStr = (new JSONObject())
.put("grant_type", Constants.REFRESH_TOKEN_GRANT_TYPE)
.put("refresh_token", refreshToken)
.put("scope", Constants.SCOPES)
.toString();
RequestBody requestBody = RequestBody.Companion.create(tokenRequestJsonStr, JSON);
Request tokenRequest = new Request.Builder()
.url(tokenEndpoint)
.addHeader(Constants.AUTHORIZATION_HEADER_NAME, Credentials.basic(keys.consumerKey,
keys.consumerSecret))
.post(requestBody)
.build();
try (Response response = client.newCall(tokenRequest).execute()) {
if (response.isSuccessful()) {
return mapTokens(response.body());
} else {
return idnTokenGeneration(keys);
}
}
}
/**
* Intercept the request and add authorization header base on available tokens.
*
* @param request Instance of the {@link Request} to intercept
* @return Intercepted request
* @throws OAuthClientException Throws when error encountered while adding authorization header
*/
private Request intercept(Request request) throws OAuthClientException {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
CacheWrapper cacheWrapper = cache.computeIfAbsent(tenantDomain, key -> {
CacheWrapper constructedWrapper = null;
try {
Keys keys = idnDynamicClientRegistration();
Tokens tokens = idnTokenGeneration(keys);
constructedWrapper = new CacheWrapper(keys, tokens);
} catch (Exception e) {
log.error("Error encountered while updating the cache", e);
}
return constructedWrapper;
});
if (cacheWrapper == null) {
throw new OAuthClientException("Failed to obtain tokens. Hence aborting request intercepting sequence");
}
return new Request.Builder(request).header(Constants.AUTHORIZATION_HEADER_NAME,
Constants.AUTHORIZATION_HEADER_PREFIX_BEARER + cacheWrapper.tokens.accessToken).build();
}
/**
* Refresh cached tokens.
*
* @throws OAuthClientException Throws when error encountered while refreshing the tokens
*/
private void refresh() throws OAuthClientException {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
CacheWrapper cacheWrapper = cache.computeIfPresent(tenantDomain, (key, value) -> {
CacheWrapper updatedCacheWrapper = null;
try {
Tokens tokens = idnTokenRefresh(value.keys, value.tokens.refreshToken);
updatedCacheWrapper = new CacheWrapper(value.keys, tokens);
} catch (Exception e) {
log.error("Error encountered while updating the cache", e);
}
return updatedCacheWrapper;
});
if (cacheWrapper == null) {
throw new OAuthClientException("Failed to refresh tokens. Hence aborting request executing process");
}
}
private Keys mapKeys(ResponseBody responseBody) throws IOException {
Keys keys = new Keys();
if (responseBody == null) {
if (log.isDebugEnabled()) {
log.debug("Received empty request body for mapping into keys");
}
return keys;
}
JsonObject jsonObject = gson.fromJson(responseBody.string(), JsonObject.class);
keys.consumerKey = jsonObject.get("clientId").getAsString();
keys.consumerSecret = jsonObject.get("clientSecret").getAsString();
return keys;
}
private Tokens mapTokens(ResponseBody responseBody) throws IOException {
Tokens tokens = new Tokens();
if (responseBody == null) {
if (log.isDebugEnabled()) {
log.debug("Received empty request body for mapping into tokens");
}
return tokens;
}
JsonObject jsonObject = gson.fromJson(responseBody.string(), JsonObject.class);
tokens.accessToken = jsonObject.get("access_token").getAsString();
tokens.refreshToken = jsonObject.get("refresh_token").getAsString();
return tokens;
}
private OAuthClientResponse mapToOAuthClientResponse(Response response) throws IOException {
return new OAuthClientResponse(response.code(),
response.body() != null ? response.body().string() : null, response.isSuccessful());
}
public void createRestClientInvokerUserIfNotExists(String tenantDomain) throws OAuthClientException {
try {
UserStoreManager userStoreManager =
PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm().getUserStoreManager();
if (!userStoreManager.isExistingUser(MultitenantUtils.getTenantAwareUsername(IDN_REST_API_INVOKER_USER))) {
if (log.isDebugEnabled()) {
log.debug("Creating user '" + IDN_REST_API_INVOKER_USER + "' in '" + tenantDomain + "' tenant domain.");
}
String[] roles = {Constants.ADMIN_ROLE_KEY};
userStoreManager.addUser(
MultitenantUtils.getTenantAwareUsername(IDN_REST_API_INVOKER_USER),
IDN_REST_API_INVOKER_USER_PWD,
roles,
null,
""
);
}
} catch (UserStoreException e) {
String msg =
"Error occurred while creating " + IDN_REST_API_INVOKER_USER + "in tenant: '" + tenantDomain + "'.";
log.error(msg);
throw new OAuthClientException(msg, e);
}
}
/**
* Holder for {@link OAuthClient} instance
*/
private static class OAuthClientHolder {
private static final OAuthClient INSTANCE = new OAuthClient();
}
/**
* Act as an internal data class for containing dcr credentials, hence no need of expose as a bean
*/
private class Keys {
String consumerKey;
String consumerSecret;
}
/**
* Act as an internal data class for containing dcr tokens, hence no need of expose as a bean
*/
private class Tokens {
String accessToken;
String refreshToken;
}
/**
* Act as an internal data class for containing cached tokens and keys, hence no need of expose as a bean
*/
private class CacheWrapper {
Keys keys;
Tokens tokens;
CacheWrapper(Keys keys, Tokens tokens) {
this.keys = keys;
this.tokens = tokens;
}
}
}

@ -18,9 +18,13 @@
package io.entgra.device.mgt.core.apimgt.extension.rest.api;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIInfo.*;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIInfo.APIInfo;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIInfo.APIRevision;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIInfo.APIRevisionDeployment;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIInfo.Documentation;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIInfo.Mediation;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIInfo.MediationPolicy;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIInfo.Scope;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
@ -29,86 +33,86 @@ import java.util.List;
public interface PublisherRESTAPIServices {
Scope[] getScopes(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo)
Scope[] getScopes()
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean isSharedScopeNameExists(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, String key)
boolean isSharedScopeNameExists(String key)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean addNewSharedScope(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, Scope scope)
boolean addNewSharedScope(Scope scope)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean updateSharedScope(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, Scope scope)
boolean updateSharedScope(Scope scope)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean deleteSharedScope(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, Scope scope)
boolean deleteSharedScope(Scope scope)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
APIInfo getApi(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, String apiUuid)
APIInfo getApi(String apiUuid)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
APIInfo[] getApis(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo)
APIInfo[] getApis()
throws APIServicesException, BadRequestException, UnexpectedResponseException;
APIInfo addAPI(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, APIInfo api)
APIInfo addAPI(APIInfo api)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean updateApi(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, APIInfo api)
boolean updateApi(APIInfo api)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean saveAsyncApiDefinition(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, String uuid,
boolean saveAsyncApiDefinition(String uuid,
String asyncApiDefinition)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
MediationPolicy[] getAllApiSpecificMediationPolicies(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo,
String apiUuid)
MediationPolicy[] getAllApiSpecificMediationPolicies(
String apiUuid)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean addApiSpecificMediationPolicy(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo,
String uuid, Mediation mediation)
boolean addApiSpecificMediationPolicy(
String uuid, Mediation mediation)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean deleteApiSpecificMediationPolicy(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo,
String uuid, Mediation mediation)
boolean deleteApiSpecificMediationPolicy(
String uuid, Mediation mediation)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean changeLifeCycleStatus(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo,
String uuid, String action)
boolean changeLifeCycleStatus(
String uuid, String action)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
APIRevision[] getAPIRevisions(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, String uuid,
APIRevision[] getAPIRevisions(String uuid,
Boolean deploymentStatus)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
APIRevision addAPIRevision(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo,
APIRevision apiRevision)
APIRevision addAPIRevision(
APIRevision apiRevision)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean deployAPIRevision(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, String uuid,
boolean deployAPIRevision(String uuid,
String apiRevisionId, List<APIRevisionDeployment> apiRevisionDeploymentList)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean undeployAPIRevisionDeployment(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo,
APIRevision apiRevisionDeployment, String uuid)
boolean undeployAPIRevisionDeployment(
APIRevision apiRevisionDeployment, String uuid)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean deleteAPIRevision(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo,
APIRevision apiRevision, String uuid)
boolean deleteAPIRevision(
APIRevision apiRevision, String uuid)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
Documentation[] getDocumentations(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo,
String uuid)
Documentation[] getDocumentations(
String uuid)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean deleteDocumentations(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo,
String uuid, String documentID)
boolean deleteDocumentations(
String uuid, String documentID)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
Documentation addDocumentation(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo,
String uuid, Documentation documentation)
Documentation addDocumentation(
String uuid, Documentation documentation)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
boolean addDocumentationContent(APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo,
String apiUuid, String docId, String docContent)
boolean addDocumentationContent(
String apiUuid, String docId, String docContent)
throws APIServicesException, BadRequestException, UnexpectedResponseException;
}

@ -21,6 +21,7 @@ package io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
@ -28,6 +29,20 @@ import java.util.Set;
*/
public class APIInfo {
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
APIInfo apiInfo = (APIInfo) o;
return Objects.equals(id, apiInfo.id);
}
@Override
public int hashCode() {
return Objects.hashCode(id);
}
private String id;
private String name;

@ -20,7 +20,23 @@ package io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer;
import org.json.JSONObject;
import java.util.Objects;
public class Subscription {
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Subscription that = (Subscription) o;
return Objects.equals(apiId, that.apiId);
}
@Override
public int hashCode() {
return Objects.hashCode(apiId);
}
private String subscriptionId;
private String applicationId;

@ -0,0 +1,44 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api.bean;
public class OAuthClientResponse {
private final int code;
private final String body;
private final boolean isSuccessful;
public OAuthClientResponse(int code, String body, boolean isSuccessful) {
this.code = code;
this.body = body;
this.isSuccessful = isSuccessful;
}
public int getCode() {
return code;
}
public String getBody() {
return body;
}
public boolean isSuccessful() {
return isSuccessful;
}
}

@ -76,4 +76,6 @@ public final class Constants {
public static final String SCOPE_PUBLISH_RESERVED_USER_PASSWORD = "&gKfyE8E4rUY4Q";
public static final String ADMIN_ROLE_KEY = "admin";
public static final String PERM_SCOPE_MAPPING_META_KEY = "perm-scope-mapping";
public static final String PLACEHOLDING_CALLBACK_URL = HTTPS_PROTOCOL + SCHEME_SEPARATOR + "localhost";
public static final String API_PUBLISHING_ENABLED_TENANT_LIST_KEY = "api-publishing-enabled-tenant-list";
}

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions;
public class OAuthClientException extends Exception {
public OAuthClientException(String msg) {
super(msg);
}
public OAuthClientException(String msg, Throwable throwable) {
super(msg, throwable);
}
}

@ -22,6 +22,8 @@ import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationService
import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServicesImpl;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.ConsumerRESTAPIServices;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.ConsumerRESTAPIServicesImpl;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.IOAuthClientService;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.OAuthClient;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServices;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServicesImpl;
import org.apache.commons.logging.Log;
@ -46,6 +48,10 @@ public class APIManagerServiceComponent {
try {
BundleContext bundleContext = componentContext.getBundleContext();
IOAuthClientService ioAuthClientService = OAuthClient.getInstance();
bundleContext.registerService(IOAuthClientService.class, ioAuthClientService, null);
APIManagerServiceDataHolder.getInstance().setIoAuthClientService(ioAuthClientService);
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
bundleContext.registerService(APIApplicationServices.class.getName(), apiApplicationServices, null);
APIManagerServiceDataHolder.getInstance().setApiApplicationServices(apiApplicationServices);

@ -19,6 +19,7 @@
package io.entgra.device.mgt.core.apimgt.extension.rest.api.internal;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.IOAuthClientService;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServices;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.ConsumerRESTAPIServices;
import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService;
@ -32,6 +33,7 @@ public class APIManagerServiceDataHolder {
private PublisherRESTAPIServices publisherRESTAPIServices;
private RealmService realmService;
private TenantManager tenantManager;
private IOAuthClientService ioAuthClientService;
private static APIManagerServiceDataHolder thisInstance = new APIManagerServiceDataHolder();
@ -40,7 +42,7 @@ public class APIManagerServiceDataHolder {
private APIManagerServiceDataHolder() {
}
static APIManagerServiceDataHolder getInstance() {
public static APIManagerServiceDataHolder getInstance() {
return thisInstance;
}
@ -102,4 +104,15 @@ public class APIManagerServiceDataHolder {
public void setConsumerRESTAPIServices(ConsumerRESTAPIServices consumerRESTAPIServices) {
this.consumerRESTAPIServices = consumerRESTAPIServices;
}
public IOAuthClientService getIoAuthClientService() {
if (ioAuthClientService == null) {
throw new IllegalStateException("OAuth client service is not initialized properly");
}
return ioAuthClientService;
}
public void setIoAuthClientService(IOAuthClientService ioAuthClientService) {
this.ioAuthClientService = ioAuthClientService;
}
}

@ -447,7 +447,7 @@ public class KeyMgtServiceImpl implements KeyMgtService {
ConsumerRESTAPIServices consumerRESTAPIServices =
KeyMgtDataHolder.getInstance().getConsumerRESTAPIServices();
io.entgra.device.mgt.core.apimgt.extension.rest.api.bean.APIMConsumer.Application[] applications =
consumerRESTAPIServices.getAllApplications(apiApplicationInfo, applicationName);
consumerRESTAPIServices.getAllApplications(applicationName);
if (applications.length == 1) {
return applications[0];
} else {

@ -114,11 +114,7 @@ public class APIPublisherServiceImpl implements APIPublisherService {
tenants.addAll(config.getTenants().getTenant());
RealmService realmService = (RealmService) PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getOSGiService(RealmService.class, null);
APIApplicationServices apiApplicationServices = APIPublisherDataHolder.getInstance().getApiApplicationServices();
PublisherRESTAPIServices publisherRESTAPIServices = APIPublisherDataHolder.getInstance().getPublisherRESTAPIServices();
APIApplicationKey apiApplicationKey;
AccessTokenInfo accessTokenInfo;
try {
boolean tenantFound = false;
@ -151,15 +147,10 @@ public class APIPublisherServiceImpl implements APIPublisherService {
if (tenantFound) {
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(apiConfig.getOwner());
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
log.info("Initiating API publishing sequence for API [ " + apiConfig.getName() + "] in domain [ " +
tenantDomain + " ]");
try {
APIPublisherUtils.createScopePublishUserIfNotExists(tenantDomain);
apiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials(
"ClientForPublisherRestCalls",
"client_credentials password refresh_token");
accessTokenInfo = apiApplicationServices.generateAccessTokenFromRegisteredApplication(
apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
} catch (APIServicesException e) {
String errorMsg = "Error occurred while generating the API application";
log.error(errorMsg, e);
@ -169,11 +160,10 @@ public class APIPublisherServiceImpl implements APIPublisherService {
try {
apiConfig.setOwner(APIUtil.getTenantAdminUserName(tenantDomain));
apiConfig.setTenantDomain(tenantDomain);
APIProvider apiProvider = API_MANAGER_FACTORY.getAPIProvider(apiConfig.getOwner());
APIIdentifier apiIdentifier = new APIIdentifier(APIUtil.replaceEmailDomain(apiConfig.getOwner()),
apiConfig.getName(), apiConfig.getVersion());
APIInfo[] apiList = publisherRESTAPIServices.getApis(apiApplicationKey, accessTokenInfo);
APIInfo[] apiList = publisherRESTAPIServices.getApis();
boolean apiFound = false;
for (int i = 0; i < apiList.length; i++) {
APIInfo apiObj = apiList[i];
@ -187,14 +177,12 @@ public class APIPublisherServiceImpl implements APIPublisherService {
String apiUuid = apiIdentifier.getUUID();
if (!apiFound) {
// add new scopes as shared scopes
addNewSharedScope(apiConfig.getScopes(), publisherRESTAPIServices, apiApplicationKey,
accessTokenInfo);
addNewSharedScope(apiConfig.getScopes(), publisherRESTAPIServices);
APIInfo api = getAPI(apiConfig, true);
APIInfo createdAPI = publisherRESTAPIServices.addAPI(apiApplicationKey, accessTokenInfo, api);
APIInfo createdAPI = publisherRESTAPIServices.addAPI(api);
apiUuid = createdAPI.getId();
if (apiConfig.getEndpointType() != null && "WS".equals(apiConfig.getEndpointType())) {
publisherRESTAPIServices.saveAsyncApiDefinition(apiApplicationKey, accessTokenInfo,
apiUuid, apiConfig.getAsyncApiDefinition());
publisherRESTAPIServices.saveAsyncApiDefinition(apiUuid, apiConfig.getAsyncApiDefinition());
}
if (CREATED_STATUS.equals(createdAPI.getLifeCycleStatus())) {
// if endpoint type "dynamic" and then add in sequence
@ -204,17 +192,14 @@ public class APIPublisherServiceImpl implements APIPublisherService {
mediation.setConfig(apiConfig.getInSequenceConfig());
mediation.setType("in");
mediation.setGlobal(false);
publisherRESTAPIServices.addApiSpecificMediationPolicy(apiApplicationKey,
accessTokenInfo, apiUuid, mediation);
publisherRESTAPIServices.addApiSpecificMediationPolicy(apiUuid, mediation);
}
publisherRESTAPIServices.changeLifeCycleStatus(apiApplicationKey, accessTokenInfo,
apiUuid, PUBLISH_ACTION);
publisherRESTAPIServices.changeLifeCycleStatus(apiUuid, PUBLISH_ACTION);
APIRevision apiRevision = new APIRevision();
apiRevision.setApiUUID(apiUuid);
apiRevision.setDescription("Initial Revision");
String apiRevisionId = publisherRESTAPIServices.addAPIRevision(apiApplicationKey,
accessTokenInfo, apiRevision).getId();
String apiRevisionId = publisherRESTAPIServices.addAPIRevision(apiRevision).getId();
APIRevisionDeployment apiRevisionDeployment = new APIRevisionDeployment();
apiRevisionDeployment.setName(API_PUBLISH_ENVIRONMENT);
@ -223,8 +208,7 @@ public class APIPublisherServiceImpl implements APIPublisherService {
List<APIRevisionDeployment> apiRevisionDeploymentList = new ArrayList<>();
apiRevisionDeploymentList.add(apiRevisionDeployment);
publisherRESTAPIServices.deployAPIRevision(apiApplicationKey, accessTokenInfo,
apiUuid, apiRevisionId, apiRevisionDeploymentList);
publisherRESTAPIServices.deployAPIRevision(apiUuid, apiRevisionId, apiRevisionDeploymentList);
}
} else {
if (WebappPublisherConfig.getInstance().isEnabledUpdateApi()) {
@ -248,20 +232,17 @@ public class APIPublisherServiceImpl implements APIPublisherService {
// upgrade to 5.0.0 first before updating from 5.0.0 to the most recent version if we
// are updating from a version that is older than 5.0.0.
addNewSharedScope(apiConfig.getScopes(), publisherRESTAPIServices, apiApplicationKey,
accessTokenInfo);
addNewSharedScope(apiConfig.getScopes(), publisherRESTAPIServices);
// Get existing API
APIInfo existingAPI = publisherRESTAPIServices.getApi(apiApplicationKey, accessTokenInfo,
apiUuid);
APIInfo existingAPI = publisherRESTAPIServices.getApi(apiUuid);
APIInfo api = getAPI(apiConfig, true);
api.setLifeCycleStatus(existingAPI.getLifeCycleStatus());
api.setId(apiUuid);
publisherRESTAPIServices.updateApi(apiApplicationKey, accessTokenInfo, api);
publisherRESTAPIServices.updateApi(api);
if (apiConfig.getEndpointType() != null && "WS".equals(apiConfig.getEndpointType())) {
publisherRESTAPIServices.saveAsyncApiDefinition(apiApplicationKey, accessTokenInfo,
apiUuid, apiConfig.getAsyncApiDefinition());
publisherRESTAPIServices.saveAsyncApiDefinition(apiUuid, apiConfig.getAsyncApiDefinition());
}
// if endpoint type "dynamic" and then add /update in sequence
@ -273,45 +254,37 @@ public class APIPublisherServiceImpl implements APIPublisherService {
mediation.setGlobal(false);
MediationPolicy[] mediationList = publisherRESTAPIServices
.getAllApiSpecificMediationPolicies(apiApplicationKey, accessTokenInfo, apiUuid);
.getAllApiSpecificMediationPolicies(apiUuid);
boolean isMediationPolicyFound = false;
for (int i = 0; i < mediationList.length; i++) {
MediationPolicy mediationPolicy = mediationList[i];
if (apiConfig.getInSequenceName().equals(mediationPolicy.getName())) {
mediation.setUuid(mediationPolicy.getId());
publisherRESTAPIServices.deleteApiSpecificMediationPolicy(apiApplicationKey,
accessTokenInfo, apiUuid, mediation);
publisherRESTAPIServices.addApiSpecificMediationPolicy(apiApplicationKey,
accessTokenInfo, apiUuid, mediation);
publisherRESTAPIServices.deleteApiSpecificMediationPolicy(apiUuid, mediation);
publisherRESTAPIServices.addApiSpecificMediationPolicy(apiUuid, mediation);
isMediationPolicyFound = true;
break;
}
}
if (!isMediationPolicyFound) {
publisherRESTAPIServices.addApiSpecificMediationPolicy(apiApplicationKey,
accessTokenInfo, apiUuid, mediation);
publisherRESTAPIServices.addApiSpecificMediationPolicy(apiUuid, mediation);
}
}
int apiRevisionCount = publisherRESTAPIServices.getAPIRevisions(apiApplicationKey,
accessTokenInfo, apiUuid, null).length;
int apiRevisionCount = publisherRESTAPIServices.getAPIRevisions(apiUuid, null).length;
if (apiRevisionCount >= 5) {
// This will retrieve the deployed revision
APIRevision[] revisionDeploymentList = publisherRESTAPIServices.getAPIRevisions(
apiApplicationKey, accessTokenInfo, apiUuid, true);
APIRevision[] revisionDeploymentList = publisherRESTAPIServices.getAPIRevisions(apiUuid, true);
if (revisionDeploymentList.length > 0) {
APIRevision latestRevisionDeployment = revisionDeploymentList[0];
publisherRESTAPIServices.undeployAPIRevisionDeployment(apiApplicationKey,
accessTokenInfo, latestRevisionDeployment, apiUuid);
publisherRESTAPIServices.undeployAPIRevisionDeployment(latestRevisionDeployment, apiUuid);
}
// This will retrieve the undeployed revision list
APIRevision[] undeployedRevisionList = publisherRESTAPIServices.getAPIRevisions(apiApplicationKey,
accessTokenInfo, apiUuid, false);
APIRevision[] undeployedRevisionList = publisherRESTAPIServices.getAPIRevisions(apiUuid, false);
if (undeployedRevisionList.length > 0) {
APIRevision earliestUndeployRevision = undeployedRevisionList[0];
publisherRESTAPIServices.deleteAPIRevision(apiApplicationKey, accessTokenInfo,
earliestUndeployRevision, apiUuid);
publisherRESTAPIServices.deleteAPIRevision(earliestUndeployRevision, apiUuid);
}
}
@ -319,8 +292,7 @@ public class APIPublisherServiceImpl implements APIPublisherService {
APIRevision apiRevision = new APIRevision();
apiRevision.setApiUUID(apiUuid);
apiRevision.setDescription("Updated Revision");
String apiRevisionId = publisherRESTAPIServices.addAPIRevision(apiApplicationKey,
accessTokenInfo, apiRevision).getId();
String apiRevisionId = publisherRESTAPIServices.addAPIRevision(apiRevision).getId();
APIRevisionDeployment apiRevisionDeployment = new APIRevisionDeployment();
apiRevisionDeployment.setName(API_PUBLISH_ENVIRONMENT);
@ -330,12 +302,10 @@ public class APIPublisherServiceImpl implements APIPublisherService {
List<APIRevisionDeployment> apiRevisionDeploymentList = new ArrayList<>();
apiRevisionDeploymentList.add(apiRevisionDeployment);
publisherRESTAPIServices.deployAPIRevision(apiApplicationKey, accessTokenInfo,
apiUuid, apiRevisionId, apiRevisionDeploymentList);
publisherRESTAPIServices.deployAPIRevision(apiUuid, apiRevisionId, apiRevisionDeploymentList);
if (CREATED_STATUS.equals(existingAPI.getLifeCycleStatus())) {
publisherRESTAPIServices.changeLifeCycleStatus(apiApplicationKey, accessTokenInfo,
apiUuid, PUBLISH_ACTION);
publisherRESTAPIServices.changeLifeCycleStatus(apiUuid, PUBLISH_ACTION);
}
}
}
@ -365,27 +335,23 @@ public class APIPublisherServiceImpl implements APIPublisherService {
apiDocumentation.setSummary(apiConfig.getApiDocumentationSummary());
apiDocumentation.setOtherTypeName(null);
Documentation[] documentList = publisherRESTAPIServices.getDocumentations(apiApplicationKey,
accessTokenInfo, apiUuid);
Documentation[] documentList = publisherRESTAPIServices.getDocumentations(apiUuid);
if (documentList.length > 0) {
for (int i = 0; i < documentList.length; i++) {
Documentation existingDoc = documentList[i];
if (existingDoc.getName().equals(apiConfig.getApiDocumentationName())
&& existingDoc.getType().equals(Documentation.DocumentationType.HOWTO.name())) {
publisherRESTAPIServices.deleteDocumentations(apiApplicationKey, accessTokenInfo,
apiUuid, existingDoc.getDocumentId());
publisherRESTAPIServices.deleteDocumentations(apiUuid, existingDoc.getDocumentId());
}
}
} else {
log.info("There is no any existing api documentation.");
}
Documentation createdDoc = publisherRESTAPIServices.addDocumentation(apiApplicationKey, accessTokenInfo,
apiUuid, apiDocumentation);
Documentation createdDoc = publisherRESTAPIServices.addDocumentation(apiUuid, apiDocumentation);
publisherRESTAPIServices.addDocumentationContent(apiApplicationKey, accessTokenInfo, apiUuid,
createdDoc.getDocumentId(), docContent);
publisherRESTAPIServices.addDocumentationContent(apiUuid, createdDoc.getDocumentId(), docContent);
}
} catch (APIManagementException | IOException | APIServicesException |
@ -411,17 +377,13 @@ public class APIPublisherServiceImpl implements APIPublisherService {
*
* @param apiScopes set of API scopes
* @param publisherRESTAPIServices {@link PublisherRESTAPIServices}
* @param apiApplicationKey API application Key
* @param accessTokenInfo Details of access token
* @throws BadRequestException if invalid payload receives to add new shared scopes.
* @throws UnexpectedResponseException if the response is not either 200 or 400.
* @throws APIServicesException if error occurred while processing the response.
*/
private void addNewSharedScope(Set<ApiScope> apiScopes, PublisherRESTAPIServices publisherRESTAPIServices,
APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo) throws BadRequestException, UnexpectedResponseException, APIServicesException {
private void addNewSharedScope(Set<ApiScope> apiScopes, PublisherRESTAPIServices publisherRESTAPIServices) throws BadRequestException, UnexpectedResponseException, APIServicesException {
for (ApiScope apiScope : apiScopes) {
if (!publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo,
apiScope.getKey())) {
if (!publisherRESTAPIServices.isSharedScopeNameExists(apiScope.getKey())) {
Scope scope = new Scope();
scope.setName(apiScope.getKey());
scope.setDescription(apiScope.getDescription());
@ -429,7 +391,7 @@ public class APIPublisherServiceImpl implements APIPublisherService {
List<String> bindings = new ArrayList<>(apiScope.getRoles());
bindings.add(ADMIN_ROLE_KEY);
scope.setBindings(bindings);
publisherRESTAPIServices.addNewSharedScope(apiApplicationKey, accessTokenInfo, scope);
publisherRESTAPIServices.addNewSharedScope(scope);
}
}
}
@ -449,20 +411,9 @@ public class APIPublisherServiceImpl implements APIPublisherService {
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
APIPublisherUtils.createScopePublishUserIfNotExists(tenantDomain);
APIApplicationKey apiApplicationKey =
apiApplicationServices.createAndRetrieveApplicationCredentials(
"ClientForPublisherRestCalls", "client_credentials password refresh_token"
);
AccessTokenInfo accessTokenInfo =
apiApplicationServices.generateAccessTokenFromRegisteredApplication(
apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
Scope scope = new Scope();
for (DefaultPermission defaultPermission : defaultPermissions.getDefaultPermissions()) {
if (!publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo,
defaultPermission.getScopeMapping().getKey())) {
if (!publisherRESTAPIServices.isSharedScopeNameExists(defaultPermission.getScopeMapping().getKey())) {
ScopeMapping scopeMapping = defaultPermission.getScopeMapping();
List<String> bindings = new ArrayList<>(
@ -472,7 +423,7 @@ public class APIPublisherServiceImpl implements APIPublisherService {
scope.setDescription(scopeMapping.getName());
scope.setDisplayName(scopeMapping.getName());
scope.setBindings(bindings);
publisherRESTAPIServices.addNewSharedScope(apiApplicationKey, accessTokenInfo, scope);
publisherRESTAPIServices.addNewSharedScope(scope);
}
}
} catch (BadRequestException | UnexpectedResponseException | APIServicesException e) {
@ -507,17 +458,6 @@ public class APIPublisherServiceImpl implements APIPublisherService {
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
try {
APIPublisherUtils.createScopePublishUserIfNotExists(tenantDomain);
apiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials("ClientForPublisherRestCalls",
"client_credentials password refresh_token");
accessTokenInfo = apiApplicationServices.generateAccessTokenFromRegisteredApplication(
apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
} catch (APIServicesException e) {
String errorMsg = "Error occurred while generating the API application";
log.error(errorMsg, e);
throw new APIManagerPublisherException(e);
}
try {
fileName =
@ -583,7 +523,7 @@ public class APIPublisherServiceImpl implements APIPublisherService {
}
}
//Set scope details which related to the scope key
Scope[] scopes = publisherRESTAPIServices.getScopes(apiApplicationKey, accessTokenInfo);
Scope[] scopes = publisherRESTAPIServices.getScopes();
for (int i = 0; i < scopes.length; i++) {
Scope relatedScope = scopes[i];
if (relatedScope.getName().equals(scopeMapping[2].toString())) {
@ -595,13 +535,13 @@ public class APIPublisherServiceImpl implements APIPublisherService {
}
scope.setBindings(rolesList);
if (publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo, scope.getName())) {
publisherRESTAPIServices.updateSharedScope(apiApplicationKey, accessTokenInfo, scope);
if (publisherRESTAPIServices.isSharedScopeNameExists(scope.getName())) {
publisherRESTAPIServices.updateSharedScope(scope);
// todo: permission changed in update path, is not handled yet.
} else {
// This scope doesn't have an api attached.
log.warn(scope.getName() + " not available as shared, add as new scope");
publisherRESTAPIServices.addNewSharedScope(apiApplicationKey, accessTokenInfo, scope);
publisherRESTAPIServices.addNewSharedScope(scope);
// add permission if not exist
try {
PermissionUtils.putPermission(permission);
@ -647,32 +587,17 @@ public class APIPublisherServiceImpl implements APIPublisherService {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
APIApplicationServices apiApplicationServices = APIPublisherDataHolder.getInstance().getApiApplicationServices();
PublisherRESTAPIServices publisherRESTAPIServices = APIPublisherDataHolder.getInstance().getPublisherRESTAPIServices();
APIApplicationKey apiApplicationKey;
AccessTokenInfo accessTokenInfo;
try {
APIPublisherUtils.createScopePublishUserIfNotExists(tenantDomain);
apiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials(
"ClientForPublisherRestCalls",
"client_credentials password refresh_token"
);
accessTokenInfo = apiApplicationServices.generateAccessTokenFromRegisteredApplication(
apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
} catch (APIServicesException e) {
String errorMsg = "Error occurred while generating the API application";
log.error(errorMsg, e);
throw new APIManagerPublisherException(e);
}
try {
Scope[] scopeList = publisherRESTAPIServices.getScopes(apiApplicationKey, accessTokenInfo);
Scope[] scopeList = publisherRESTAPIServices.getScopes();
Map<String, String> permScopeMap = APIPublisherDataHolder.getInstance().getPermScopeMapping();
if (permissions.length != 0) {
updateScopes(roleName, publisherRESTAPIServices, apiApplicationKey, accessTokenInfo, scopeList, permissions, permScopeMap, false);
updateScopes(roleName, publisherRESTAPIServices, scopeList, permissions, permScopeMap, false);
}
if (removedPermissions.length != 0) {
updateScopes(roleName, publisherRESTAPIServices, apiApplicationKey, accessTokenInfo, scopeList, removedPermissions, permScopeMap, true);
updateScopes(roleName, publisherRESTAPIServices, scopeList, removedPermissions, permScopeMap, true);
}
try {
@ -704,8 +629,6 @@ public class APIPublisherServiceImpl implements APIPublisherService {
*
* @param roleName Role Name
* @param publisherRESTAPIServices {@link PublisherRESTAPIServices}
* @param apiApplicationKey {@link APIApplicationKey}
* @param accessTokenInfo {@link AccessTokenInfo}
* @param scopeList scope list returning from APIM
* @param permissions List of permissions
* @param permScopeMap Permission Scope map
@ -713,7 +636,6 @@ public class APIPublisherServiceImpl implements APIPublisherService {
* @throws APIManagerPublisherException If the method receives invalid permission to update.
*/
private void updateScopes (String roleName, PublisherRESTAPIServices publisherRESTAPIServices,
APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo,
Scope[] scopeList, String[] permissions, Map<String, String> permScopeMap, boolean removingPermissions )
throws APIManagerPublisherException {
for (String permission : permissions) {
@ -752,8 +674,8 @@ public class APIPublisherServiceImpl implements APIPublisherService {
scope.setBindings(existingRoleList);
try {
if (publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo, scope.getName())) {
publisherRESTAPIServices.updateSharedScope(apiApplicationKey, accessTokenInfo, scope);
if (publisherRESTAPIServices.isSharedScopeNameExists(scope.getName())) {
publisherRESTAPIServices.updateSharedScope(scope);
} else {
// todo: come to this level means, that scope is removed from API, but haven't removed from the scope-role-permission-mappings list
log.warn(scope.getName() + " not available as shared scope");

@ -20,6 +20,8 @@ package io.entgra.device.mgt.core.apimgt.webapp.publisher;
import com.google.gson.Gson;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.constants.Constants;
import io.entgra.device.mgt.core.apimgt.webapp.publisher.config.Tenants;
import io.entgra.device.mgt.core.apimgt.webapp.publisher.config.WebappPublisherConfig;
import io.entgra.device.mgt.core.apimgt.webapp.publisher.dto.ApiScope;
import io.entgra.device.mgt.core.apimgt.webapp.publisher.exception.APIManagerPublisherException;
import io.entgra.device.mgt.core.apimgt.webapp.publisher.internal.APIPublisherDataHolder;
@ -37,9 +39,13 @@ import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.ServerStartupObserver;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Stack;
public class APIPublisherStartupHandler implements ServerStartupObserver {
@ -112,6 +118,7 @@ public class APIPublisherStartupHandler implements ServerStartupObserver {
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
updateApiPublishingEnabledTenants(tenantDomain);
updateScopeMetadataEntryWithDefaultScopes();
} finally {
PrivilegedCarbonContext.endTenantFlow();
@ -202,4 +209,31 @@ public class APIPublisherStartupHandler implements ServerStartupObserver {
log.error("Error encountered while updating permission scope mapping metadata with default scopes");
}
}
private void updateApiPublishingEnabledTenants(String superTenantDomain) {
MetadataManagementService metadataManagementService = APIPublisherDataHolder.getInstance().getMetadataManagementService();
WebappPublisherConfig webappPublisherConfig = WebappPublisherConfig.getInstance();
Metadata tenantsEntry = new Metadata();
List<String> tenants = new ArrayList<>();
tenants.add(superTenantDomain);
tenants.addAll(webappPublisherConfig.getTenants().getTenant());
tenantsEntry.setMetaKey(Constants.API_PUBLISHING_ENABLED_TENANT_LIST_KEY);
tenantsEntry.setMetaValue(gson.toJson(tenants));
try {
if (metadataManagementService.retrieveMetadata(Constants.API_PUBLISHING_ENABLED_TENANT_LIST_KEY) == null) {
metadataManagementService.createMetadata(tenantsEntry);
return;
}
metadataManagementService.updateMetadata(tenantsEntry);
} catch (MetadataKeyAlreadyExistsException e) {
log.error("Metadata entry already exists for " + Constants.API_PUBLISHING_ENABLED_TENANT_LIST_KEY);
} catch (MetadataManagementException e) {
log.error("Error encountered while updating api publish enabled tenants metadata with default scopes");
}
}
}

@ -37,8 +37,8 @@
<module>io.entgra.device.mgt.core.apimgt.application.extension</module>
<module>io.entgra.device.mgt.core.apimgt.application.extension.api</module>
<module>io.entgra.device.mgt.core.apimgt.annotations</module>
<module>io.entgra.device.mgt.core.apimgt.keymgt.extension</module>
<module>io.entgra.device.mgt.core.apimgt.keymgt.extension.api</module>
<!-- <module>io.entgra.device.mgt.core.apimgt.keymgt.extension</module>-->
<!-- <module>io.entgra.device.mgt.core.apimgt.keymgt.extension.api</module>-->
<module>io.entgra.device.mgt.core.apimgt.analytics.extension</module>
<module>io.entgra.device.mgt.core.apimgt.extension.rest.api</module>
</modules>

@ -19,8 +19,13 @@
package io.entgra.device.mgt.core.application.mgt.core.util;
import io.entgra.device.mgt.core.apimgt.application.extension.APIManagementProviderService;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.ApiApplicationProfile;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.IdnAuthenticationProfile;
import io.entgra.device.mgt.core.apimgt.application.extension.dto.ApiApplicationKey;
import io.entgra.device.mgt.core.apimgt.application.extension.exception.APIManagerException;
import io.entgra.device.mgt.core.apimgt.application.extension.exception.IdnAuthenticationException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
import io.entgra.device.mgt.core.application.mgt.common.dto.ApiRegistrationProfile;
import io.entgra.device.mgt.core.identity.jwt.client.extension.JWTClient;
import io.entgra.device.mgt.core.identity.jwt.client.extension.dto.AccessTokenInfo;
@ -58,15 +63,26 @@ public class OAuthUtils {
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username);
String password = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminPassword();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
APIManagementProviderService apiManagementProviderService = (APIManagementProviderService) ctx.
getOSGiService(APIManagementProviderService.class, null);
IdnAuthenticationProfile idnAuthenticationProfile = new IdnAuthenticationProfile();
idnAuthenticationProfile.setUsername(username);
idnAuthenticationProfile.setPassword(password);
ApiApplicationProfile apiApplicationProfile = new ApiApplicationProfile();
apiApplicationProfile.setApplicationName(registrationProfile.getApplicationName());
apiApplicationProfile.setTags(registrationProfile.getTags());
apiApplicationProfile.setGrantTypes("refresh_token client_credentials password");
apiApplicationKeyInfo = apiManagementProviderService.
generateAndRetrieveApplicationKeys(registrationProfile.getApplicationName(),
registrationProfile.getTags(), Constants.ApplicationInstall.DEFAULT_TOKEN_TYPE,
username, registrationProfile.isAllowedToAllDomains(),
Constants.ApplicationInstall.DEFAULT_VALIDITY_PERIOD, PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminPassword(), null, null, null, false);
registerApiApplication(idnAuthenticationProfile, apiApplicationProfile);
} catch (IdnAuthenticationException | BadRequestException | UnexpectedResponseException e) {
String msg = "Error encountered while registering api application";
log.error(msg);
throw new APIManagerException(msg, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
@ -80,7 +96,7 @@ public class OAuthUtils {
JWTClientManagerService jwtClientManagerService = (JWTClientManagerService) ctx.
getOSGiService(JWTClientManagerService.class, null);
JWTClient jwtClient = jwtClientManagerService.getJWTClient();
return jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(), apiApplicationKey.getConsumerSecret(),
return jwtClient.getAccessToken(apiApplicationKey.getClient_id(), apiApplicationKey.getClient_secret(),
username, Constants.ApplicationInstall.SUBSCRIPTION_SCOPE);
} catch (JWTClientException e) {
String errorMsg = "Error while generating an OAuth token for user " + username;

@ -19,22 +19,15 @@
package io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import io.entgra.device.mgt.core.apimgt.application.extension.APIManagementProviderService;
import io.entgra.device.mgt.core.apimgt.application.extension.APIManagementProviderServiceImpl;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.ApiApplicationProfile;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.IdnAuthenticationProfile;
import io.entgra.device.mgt.core.apimgt.application.extension.dto.ApiApplicationKey;
import io.entgra.device.mgt.core.apimgt.application.extension.exception.APIManagerException;
import io.entgra.device.mgt.core.apimgt.application.extension.internal.APIApplicationManagerExtensionDataHolder;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServicesImpl;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
import io.entgra.device.mgt.core.apimgt.keymgt.extension.DCRResponse;
import io.entgra.device.mgt.core.apimgt.keymgt.extension.TokenRequest;
import io.entgra.device.mgt.core.apimgt.keymgt.extension.TokenResponse;
import io.entgra.device.mgt.core.apimgt.keymgt.extension.exception.KeyMgtException;
import io.entgra.device.mgt.core.apimgt.keymgt.extension.service.KeyMgtService;
import io.entgra.device.mgt.core.apimgt.keymgt.extension.service.KeyMgtServiceImpl;
import io.entgra.device.mgt.core.apimgt.application.extension.exception.IdnAuthenticationException;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.Token;
import io.entgra.device.mgt.core.apimgt.application.extension.bean.TokenCreationProfile;
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
import io.entgra.device.mgt.core.application.mgt.common.ApplicationInstallResponse;
import io.entgra.device.mgt.core.application.mgt.common.SubscriptionType;
import io.entgra.device.mgt.core.application.mgt.common.exception.SubscriptionManagementException;
@ -135,7 +128,6 @@ import java.util.List;
import java.util.Properties;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@Path("/devices")
public class DeviceManagementServiceImpl implements DeviceManagementService {
@ -956,51 +948,46 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
}
String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
String applicationName = type.replace(" ", "").replace("_", "")
+ "_" + tenantDomain;
KeyMgtService keyMgtService = new KeyMgtServiceImpl();
APIManagementProviderService apiManagementProviderService = DeviceMgtAPIUtils.getAPIManagementService();
try {
ApiApplicationKey apiApplicationKey;
try {
APIApplicationServices apiApplicationServices = DeviceMgtAPIUtils.getApiApplicationServices();
APIApplicationKey adminDCRResponse = apiApplicationServices.createAndRetrieveApplicationCredentials(
"ClientForJWTTokenGeneration",
"client_credentials password refresh_token urn:ietf:params:oauth:grant-type:jwt-bearer"
);
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
JWTClientManagerService jwtClientManagerService = (JWTClientManagerService) ctx.
getOSGiService(JWTClientManagerService.class, null);
JWTClient jwtClient = jwtClientManagerService.getJWTClient();
AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(adminDCRResponse.getClientId(),
adminDCRResponse.getClientSecret(),
username, "appm:subscribe apim:admin apim:api_key apim:app_import_export apim:app_manage" +
" apim:store_settings apim:sub_alert_manage apim:sub_manage apim:subscribe openid perm:device:enroll " +
"perm:devices:details perm:devices:features perm:devices:search perm:devices:view perm:groups:groups " +
"perm:users:send-invitation");
APIManagementProviderService apiManagementProviderService = DeviceMgtAPIUtils.getAPIManagementService();
apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(applicationName,
new String[] {"device_management"}, "PRODUCTION", null, false, String.valueOf(validityTime),
null, accessTokenInfo.getAccessToken(), null, null,true);
} catch (JWTClientException e) {
String msg = "Error while generating an application tokens for Tenant Admin.";
String adminUserName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName();
String adminPassword = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminPassword();
IdnAuthenticationProfile idnAuthenticationProfile = new IdnAuthenticationProfile();
idnAuthenticationProfile.setUsername(adminUserName);
idnAuthenticationProfile.setPassword(adminPassword);
ApiApplicationProfile apiApplicationProfile = new ApiApplicationProfile();
apiApplicationProfile.setApplicationName(applicationName);
apiApplicationProfile.setTags(new String[] {"device_management"});
apiApplicationProfile.setGrantTypes("client_credentials password refresh_token");
apiApplicationKey = apiManagementProviderService.registerApiApplication(idnAuthenticationProfile, apiApplicationProfile);
} catch (UserStoreException e) {
String msg = "Failed to retrieve the tenant" + tenantDomain + "'";
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} catch (APIServicesException e) {
String msg = "Error while generating api Application";
} catch (IdnAuthenticationException |
io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException |
UnexpectedResponseException e) {
String msg = "Error encountered while registering api application";
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
//todo call REST APIs
deviceConfig.setClientId(apiApplicationKey.getConsumerKey());
deviceConfig.setClientSecret(apiApplicationKey.getConsumerSecret());
deviceConfig.setClientId(apiApplicationKey.getClient_id());
deviceConfig.setClientSecret(apiApplicationKey.getClient_secret());
StringBuilder scopes = new StringBuilder("device:" + type.replace(" ", "") + ":" + id);
for (String topic : mqttEventTopicStructure) {
@ -1018,13 +1005,15 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
// add scopes for update operation /tenantDomain/deviceType/deviceId/update/operation
scopes.append(" perm:topic:pub:" + tenantDomain + ":" + type + ":" + id + ":update:operation");
TokenRequest tokenRequest = new TokenRequest(apiApplicationKey.getConsumerKey(),
apiApplicationKey.getConsumerSecret(),
null, scopes.toString(), "client_credentials", null,
null, null, null, validityTime);
TokenResponse tokenResponse = keyMgtService.generateAccessToken(tokenRequest);
deviceConfig.setAccessToken(tokenResponse.getAccessToken());
deviceConfig.setRefreshToken(tokenResponse.getRefreshToken());
TokenCreationProfile tokenCreationProfile = new TokenCreationProfile();
tokenCreationProfile.setGrantType("client_credentials");
tokenCreationProfile.setScope(scopes.toString());
tokenCreationProfile.setBasicAuthUsername(apiApplicationKey.getClient_id());
tokenCreationProfile.setBasicAuthPassword(apiApplicationKey.getClient_secret());
Token token = apiManagementProviderService.getToken(tokenCreationProfile);
deviceConfig.setAccessToken(token.getAccess_token());
deviceConfig.setRefreshToken(token.getRefresh_token());
try {
deviceConfig.setPlatformConfiguration(deviceManagementProviderService.getConfiguration(type));
@ -1039,16 +1028,6 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
deviceConfig.setHttpGateway("http://" + System.getProperty("iot.gateway.host") + ":" + System.getProperty("iot.gateway.http.port"));
deviceConfig.setHttpsGateway("https://" + System.getProperty("iot.gateway.host") + ":" + System.getProperty("iot.gateway.https.port"));
} catch (KeyMgtException e) {
String msg = "Error occurred while creating oauth application, device id : " + id + ", device type : " + type;
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} catch (io.entgra.device.mgt.core.apimgt.keymgt.extension.exception.BadRequestException e) {
String msg = "Error occurred while generating token, device id : " + id + ", device type : " + type;
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} catch (APIManagerException e) {
String msg = "Error while calling rest Call for application key generation";
log.error(msg, e);

@ -142,36 +142,18 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser
*/
private void publishScopesToTenant(String tenantDomain) throws TenantManagementException {
if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
APIApplicationServices apiApplicationServices = DeviceManagementDataHolder.getInstance().getApiApplicationServices();
APIApplicationKey apiApplicationKey;
AccessTokenInfo accessTokenInfo;
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
APIPublisherUtils.createScopePublishUserIfNotExists(tenantDomain);
apiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials(
"ClientForScopePublish",
"client_credentials password refresh_token");
accessTokenInfo = apiApplicationServices.generateAccessTokenFromRegisteredApplication(
apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
} catch (APIServicesException e) {
msg = "Error occurred while generating the API application for tenant: '" + tenantDomain + "'.";
log.error(msg, e);
throw new TenantManagementException(msg, e);
}
try {
PublisherRESTAPIServices publisherRESTAPIServices = DeviceManagementDataHolder.getInstance().getPublisherRESTAPIServices();
Scope[] superTenantScopes = getAllScopesFromSuperTenant(apiApplicationServices, publisherRESTAPIServices);
Scope[] superTenantScopes = getAllScopesFromSuperTenant(publisherRESTAPIServices);
if (superTenantScopes != null) {
if (log.isDebugEnabled()) {
log.debug("Number of super tenant scopes already published - " + superTenantScopes.length);
}
Scope[] subTenantScopes = publisherRESTAPIServices.getScopes(apiApplicationKey, accessTokenInfo);
Scope[] subTenantScopes = publisherRESTAPIServices.getScopes();
if (subTenantScopes.length > 0) {
// If there is already existing scopes on the sub tenant space then do a comparison with the
@ -211,8 +193,7 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser
if (log.isDebugEnabled()) {
log.debug("Starting to add new/updated shared scopes to the tenant: '" + tenantDomain + "'.");
}
publishSharedScopes(missingScopes, publisherRESTAPIServices, apiApplicationKey,
accessTokenInfo);
publishSharedScopes(missingScopes, publisherRESTAPIServices);
}
for (Scope subTenantScope : subTenantScopes) {
@ -242,10 +223,9 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser
log.debug("Starting to delete shared scopes from the tenant: '" + tenantDomain + "'.");
}
for (Scope deletedScope : deletedScopes) {
if (publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo,
deletedScope.getName())) {
if (publisherRESTAPIServices.isSharedScopeNameExists(deletedScope.getName())) {
Scope scope = createScopeObject(deletedScope);
publisherRESTAPIServices.deleteSharedScope(apiApplicationKey, accessTokenInfo, scope);
publisherRESTAPIServices.deleteSharedScope(scope);
}
}
}
@ -254,8 +234,7 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser
log.debug("Starting to publish shared scopes to newly created tenant: '" + tenantDomain + "'.");
}
publishSharedScopes(Arrays.asList(superTenantScopes), publisherRESTAPIServices,
apiApplicationKey, accessTokenInfo);
publishSharedScopes(Arrays.asList(superTenantScopes), publisherRESTAPIServices);
}
} else {
msg = "Unable to publish scopes to sub tenants due to super tenant scopes list being empty.";
@ -334,15 +313,13 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser
/**
* Get all the scopes from the super tenant space
* @param apiApplicationServices {@link APIApplicationServices} is used to create an OAuth application and retrieve client ID and secret
* @param publisherRESTAPIServices {@link PublisherRESTAPIServices} is used to get all scopes under a given tenant using client credentials
* @return array of {@link Scope}
* @throws BadRequestException if an invalid request is sent to the API Manager Publisher REST API Service
* @throws UnexpectedResponseException if an unexpected response is received from the API Manager Publisher REST API Service
* @throws TenantManagementException if an error occurred while processing the request sent to API Manager Publisher REST API Service
*/
private Scope[] getAllScopesFromSuperTenant(APIApplicationServices apiApplicationServices,
PublisherRESTAPIServices publisherRESTAPIServices) throws BadRequestException,
private Scope[] getAllScopesFromSuperTenant(PublisherRESTAPIServices publisherRESTAPIServices) throws BadRequestException,
UnexpectedResponseException, TenantManagementException {
try {
@ -350,12 +327,7 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser
// in order to see if any new scopes were added or deleted
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true);
APIApplicationKey superTenantApiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials(
"ClientForScopePublish",
"client_credentials password refresh_token");
AccessTokenInfo superTenantAccessToken = apiApplicationServices.generateAccessTokenFromRegisteredApplication(
superTenantApiApplicationKey.getClientId(), superTenantApiApplicationKey.getClientSecret());
return publisherRESTAPIServices.getScopes(superTenantApiApplicationKey, superTenantAccessToken);
return publisherRESTAPIServices.getScopes();
} catch (APIServicesException e) {
msg = "Error occurred while retrieving access token from super tenant";
log.error(msg, e);
@ -369,21 +341,17 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser
* Add shared scopes to the tenant space.
* @param scopeList {@link List} of {@link Scope}
* @param publisherRESTAPIServices {@link PublisherRESTAPIServices} is used to add shared scopes to a given tenant using client credentials
* @param apiApplicationKey {@link APIApplicationKey} contains client credentials of the OAuth application
* @param accessTokenInfo {@link AccessTokenInfo} contains token information generated from the client credentials
* @throws BadRequestException if an invalid request is sent to the API Manager Publisher REST API Service
* @throws UnexpectedResponseException if an unexpected response is received from the API Manager Publisher REST API Service
* @throws APIServicesException if an error occurred while processing the request sent to API Manager Publisher REST API Service
*/
private void publishSharedScopes (List<Scope> scopeList, PublisherRESTAPIServices publisherRESTAPIServices,
APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo)
private void publishSharedScopes (List<Scope> scopeList, PublisherRESTAPIServices publisherRESTAPIServices)
throws BadRequestException, UnexpectedResponseException, APIServicesException {
for (Scope tenantScope : scopeList) {
if (!publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo,
tenantScope.getName())) {
if (!publisherRESTAPIServices.isSharedScopeNameExists(tenantScope.getName())) {
Scope scope = createScopeObject(tenantScope);
publisherRESTAPIServices.addNewSharedScope(apiApplicationKey, accessTokenInfo, scope);
publisherRESTAPIServices.addNewSharedScope(scope);
}
}
}

@ -55,25 +55,6 @@
<send/>
</outSequence>
</resource>
<resource methods="DELETE" url-mapping="/unregister" faultSequence="_api_registration_fault_">
<inSequence>
<property name="uri.var.portnum" expression="get-property('system','iot.core.https.port')"/>
<property name="uri.var.hostname" expression="get-property('system','iot.core.host')"/>
<send>
<endpoint>
<http uri-template="https://{uri.var.hostname}:{uri.var.portnum}/api-application-registration">
<timeout>
<duration>60000</duration>
<responseAction>fault</responseAction>
</timeout>
</http>
</endpoint>
</send>
</inSequence>
<outSequence>
<send/>
</outSequence>
</resource>
<handlers>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerCacheExtensionHandler"/>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.common.SynapsePropertiesHandler"/>

@ -36,7 +36,7 @@
<modules>
<module>io.entgra.device.mgt.core.apimgt.webapp.publisher.feature</module>
<module>io.entgra.device.mgt.core.apimgt.application.extension.feature</module>
<module>io.entgra.device.mgt.core.apimgt.keymgt.extension.feature</module>
<!-- <module>io.entgra.device.mgt.core.apimgt.keymgt.extension.feature</module>-->
<module>io.entgra.device.mgt.core.apimgt.analytics.extension.feature</module>
<module>io.entgra.device.mgt.core.apimgt.extension.rest.api.feature</module>
</modules>

Loading…
Cancel
Save