Merge pull request #290 from milanperera/apim

Fixed APIM publishing issues
revert-70aa11f8
Milan Perera 8 years ago
commit 64da754ab2

@ -42,12 +42,12 @@ import javax.ws.rs.core.Response;
public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegistrationService { public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegistrationService {
private static final Log log = LogFactory.getLog(ApiApplicationRegistrationServiceImpl.class); private static final Log log = LogFactory.getLog(ApiApplicationRegistrationServiceImpl.class);
@Path("register/tenants/{tenantDomain}") @Path("register/tenants")
@POST @POST
public Response register(@PathParam("tenantDomain") String tenantDomain, public Response register(@QueryParam("tenantDomain") String tenantDomain,
@QueryParam("applicationName") String applicationName) { @QueryParam("applicationName") String applicationName) {
String authenticatedTenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); String authenticatedTenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
if (authenticatedTenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { if (!authenticatedTenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
return Response.status(Response.Status.NOT_ACCEPTABLE).build(); return Response.status(Response.Status.NOT_ACCEPTABLE).build();
} }
try { try {

@ -21,7 +21,7 @@ import java.util.List;
/** /**
* this filter check for permission for the request * this filter check for permission for the request
*/ */
public class ApiPermissionFilter implements Filter{ public class ApiPermissionFilter implements Filter {
private static final Log log = LogFactory.getLog(ApiPermissionFilter.class); private static final Log log = LogFactory.getLog(ApiPermissionFilter.class);
private static final String UI_EXECUTE = "ui.execute"; private static final String UI_EXECUTE = "ui.execute";
private static final String PERMISSION_CONFIG_PATH = File.separator + "META-INF" + File.separator private static final String PERMISSION_CONFIG_PATH = File.separator + "META-INF" + File.separator
@ -53,16 +53,9 @@ public class ApiPermissionFilter implements Filter{
if (servletRequest instanceof HttpServletRequest) { if (servletRequest instanceof HttpServletRequest) {
String uri = ((HttpServletRequest)servletRequest).getRequestURI(); String uri = ((HttpServletRequest)servletRequest).getRequestURI();
boolean status = false; boolean status = false;
if (uri.contains("register/tenants")) { String urlPermission = getPermission(uri);
String urlPermission = getPermission("/register/tenants/*"); if (urlPermission != null) {
if (urlPermission != null) { status = isUserAuthorized(PERMISSION_PREFIX + urlPermission, UI_EXECUTE);
status = isUserAuthorized(PERMISSION_PREFIX + urlPermission, UI_EXECUTE);
}
} else {
String urlPermission = getPermission(uri);
if (urlPermission != null) {
status = isUserAuthorized(PERMISSION_PREFIX + urlPermission, UI_EXECUTE);
}
} }
if (status) { if (status) {
filterChain.doFilter(servletRequest, servletResponse); filterChain.doFilter(servletRequest, servletResponse);

@ -31,7 +31,7 @@
<Permission> <Permission>
<name>Register tenant specific application</name> <name>Register tenant specific application</name>
<path>/device-mgt/admin</path> <path>/device-mgt/admin</path>
<url>/register/tenants/*</url> <url>/register/tenants</url>
<method>POST</method> <method>POST</method>
<scope>super_admin_user</scope> <scope>super_admin_user</scope>
</Permission> </Permission>

@ -63,6 +63,10 @@
<groupId>com.googlecode.json-simple.wso2</groupId> <groupId>com.googlecode.json-simple.wso2</groupId>
<artifactId>json-simple</artifactId> <artifactId>json-simple</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.registry</groupId>
<artifactId>org.wso2.carbon.registry.indexing</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -103,7 +107,9 @@
org.wso2.carbon.utils.multitenancy, org.wso2.carbon.utils.multitenancy,
org.json.simple, org.json.simple,
org.wso2.carbon.context, org.wso2.carbon.context,
org.wso2.carbon.base org.wso2.carbon.base,
org.wso2.carbon.registry.core.*;resolution:=optional,
org.wso2.carbon.registry.indexing.*; version="${carbon.registry.imp.pkg.version.range}"
</Import-Package> </Import-Package>
<Export-Package> <Export-Package>
!org.wso2.carbon.apimgt.application.extension.internal, !org.wso2.carbon.apimgt.application.extension.internal,

@ -35,6 +35,7 @@ import org.wso2.carbon.apimgt.application.extension.exception.APIManagerExceptio
import org.wso2.carbon.apimgt.application.extension.util.APIManagerUtil; import org.wso2.carbon.apimgt.application.extension.util.APIManagerUtil;
import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.impl.APIManagerFactory; import org.wso2.carbon.apimgt.impl.APIManagerFactory;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
@ -57,6 +58,7 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe
String username, boolean isAllowedAllDomains) String username, boolean isAllowedAllDomains)
throws APIManagerException { throws APIManagerException {
try { try {
APIManagerUtil.loadTenantRegistry();
APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username);
String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain()); String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain());
int applicationId = createApplicationAndSubscribeToAllAPIs(apiApplicationName, username); int applicationId = createApplicationAndSubscribeToAllAPIs(apiApplicationName, username);
@ -121,6 +123,7 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe
boolean isAllowedAllDomains, String keyType) boolean isAllowedAllDomains, String keyType)
throws APIManagerException { throws APIManagerException {
try { try {
APIManagerUtil.loadTenantRegistry();
APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username);
if (apiConsumer != null) { if (apiConsumer != null) {
String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain()); String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain());
@ -177,6 +180,7 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe
@Override @Override
public void removeAPIApplication(String applicationName, String username) throws APIManagerException { public void removeAPIApplication(String applicationName, String username) throws APIManagerException {
try { try {
APIManagerUtil.loadTenantRegistry();
APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username);
if (apiConsumer != null) { if (apiConsumer != null) {
String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain()); String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain());
@ -203,6 +207,7 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe
boolean isAllowedAllDomains) boolean isAllowedAllDomains)
throws APIManagerException { throws APIManagerException {
try { try {
APIManagerUtil.loadTenantRegistry();
APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username);
String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain()); String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain());
int applicationId = createApplicationAndSubscribeToAPIs(apiApplicationName, tags, username); int applicationId = createApplicationAndSubscribeToAPIs(apiApplicationName, tags, username);
@ -405,6 +410,9 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe
int applicationId = createApplication(apiConsumer, apiApplicationName, username, groupId); int applicationId = createApplication(apiConsumer, apiApplicationName, username, groupId);
String tenantDomain = MultitenantUtils.getTenantDomain(username); String tenantDomain = MultitenantUtils.getTenantDomain(username);
Set<API> userVisibleAPIs = apiConsumer.getAllPublishedAPIs(tenantDomain); Set<API> userVisibleAPIs = apiConsumer.getAllPublishedAPIs(tenantDomain);
if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
userVisibleAPIs.addAll(apiConsumer.getAllPublishedAPIs(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME));
}
Subscriber subscriber = apiConsumer.getSubscriber(username); Subscriber subscriber = apiConsumer.getSubscriber(username);
Set<SubscribedAPI> subscribedAPIs = apiConsumer.getSubscribedAPIs(subscriber); Set<SubscribedAPI> subscribedAPIs = apiConsumer.getSubscribedAPIs(subscriber);
for (API visibleApi : userVisibleAPIs) { for (API visibleApi : userVisibleAPIs) {
@ -441,4 +449,5 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe
throw new APIManagerException("Unable to get groupIds of user " + username, e); throw new APIManagerException("Unable to get groupIds of user " + username, e);
} }
} }
} }

@ -18,6 +18,8 @@
package org.wso2.carbon.apimgt.application.extension.internal; package org.wso2.carbon.apimgt.application.extension.internal;
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService; import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
import org.wso2.carbon.registry.core.service.TenantRegistryLoader;
import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.user.core.tenant.TenantManager; import org.wso2.carbon.user.core.tenant.TenantManager;
@ -26,6 +28,8 @@ public class APIApplicationManagerExtensionDataHolder {
private APIManagementProviderService apiManagementProviderService; private APIManagementProviderService apiManagementProviderService;
private RealmService realmService; private RealmService realmService;
private TenantManager tenantManager; private TenantManager tenantManager;
private TenantRegistryLoader tenantRegistryLoader;
private TenantIndexingLoader indexLoader;
private APIApplicationManagerExtensionDataHolder() { private APIApplicationManagerExtensionDataHolder() {
} }
@ -66,4 +70,20 @@ public class APIApplicationManagerExtensionDataHolder {
public TenantManager getTenantManager() { public TenantManager getTenantManager() {
return tenantManager; return tenantManager;
} }
public void setTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader){
this.tenantRegistryLoader = tenantRegistryLoader;
}
public TenantRegistryLoader getTenantRegistryLoader(){
return tenantRegistryLoader;
}
public void setIndexLoaderService(TenantIndexingLoader indexLoader) {
this.indexLoader = indexLoader;
}
public TenantIndexingLoader getIndexLoaderService(){
return indexLoader;
}
} }

@ -23,10 +23,24 @@ import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;; import org.osgi.service.component.ComponentContext;;
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService; import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderServiceImpl; import org.wso2.carbon.apimgt.application.extension.APIManagementProviderServiceImpl;
import org.wso2.carbon.registry.core.service.TenantRegistryLoader;
import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
/** /**
* @scr.component name="org.wso2.carbon.apimgt.application.extension.internal.APIApplicationManagerExtensionServiceComponent" * @scr.component name="org.wso2.carbon.apimgt.application.extension.internal.APIApplicationManagerExtensionServiceComponent"
* @scr.reference name="tenant.registryloader"
* interface="org.wso2.carbon.registry.core.service.TenantRegistryLoader"
* cardinality="1..1"
* policy="dynamic"
* bind="setTenantRegistryLoader"
* unbind="unsetTenantRegistryLoader"
* @scr.reference name="tenant.indexloader"
* interface="org.wso2.carbon.registry.indexing.service.TenantIndexingLoader"
* cardinality="1..1"
* policy="dynamic"
* bind="setIndexLoader"
* unbind="unsetIndexLoader"
* @scr.reference name="realm.service" * @scr.reference name="realm.service"
* immediate="true" * immediate="true"
* interface="org.wso2.carbon.user.core.service.RealmService" * interface="org.wso2.carbon.user.core.service.RealmService"
@ -53,6 +67,25 @@ public class APIApplicationManagerExtensionServiceComponent {
//do nothing //do nothing
} }
protected void setTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) {
APIApplicationManagerExtensionDataHolder.getInstance().setTenantRegistryLoader(tenantRegistryLoader);
}
protected void unsetTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) {
APIApplicationManagerExtensionDataHolder.getInstance().setTenantRegistryLoader(null);
}
protected void setIndexLoader(TenantIndexingLoader indexLoader) {
if (indexLoader != null && log.isDebugEnabled()) {
log.debug("IndexLoader service initialized");
}
APIApplicationManagerExtensionDataHolder.getInstance().setIndexLoaderService(indexLoader);
}
protected void unsetIndexLoader(TenantIndexingLoader indexLoader) {
APIApplicationManagerExtensionDataHolder.getInstance().setIndexLoaderService(null);
}
/** /**
* Sets Realm Service. * Sets Realm Service.
* *

@ -23,6 +23,8 @@ import org.wso2.carbon.apimgt.application.extension.exception.APIManagerExceptio
import org.wso2.carbon.apimgt.application.extension.internal.APIApplicationManagerExtensionDataHolder; import org.wso2.carbon.apimgt.application.extension.internal.APIApplicationManagerExtensionDataHolder;
import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.service.TenantRegistryLoader;
import org.wso2.carbon.user.api.TenantManager; import org.wso2.carbon.user.api.TenantManager;
import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreException;
@ -52,4 +54,18 @@ public final class APIManagerUtil {
public static String getTenantDomain() { public static String getTenantDomain() {
return PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); return PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
} }
public static void loadTenantRegistry() throws APIManagerException {
String tenantDomain = getTenantDomain();
try {
int tenantId = getTenantId(tenantDomain);
TenantRegistryLoader tenantRegistryLoader =
APIApplicationManagerExtensionDataHolder.getInstance().getTenantRegistryLoader();
APIApplicationManagerExtensionDataHolder.getInstance().getIndexLoaderService().loadTenantIndex(tenantId);
tenantRegistryLoader.loadTenantRegistry(tenantId);
} catch (RegistryException e) {
throw new APIManagerException("Error occured while loading registry for tenant '" + tenantDomain + "'");
}
}
} }

@ -289,8 +289,7 @@ public class APIPublisherUtil {
apiConfig.setTransports(transports); apiConfig.setTransports(transports);
String sharingValueParam = servletContext.getInitParameter(PARAM_SHARED_WITH_ALL_TENANTS); String sharingValueParam = servletContext.getInitParameter(PARAM_SHARED_WITH_ALL_TENANTS);
boolean isSharedWithAllTenants = (sharingValueParam == null || (!sharingValueParam.isEmpty()) boolean isSharedWithAllTenants = Boolean.parseBoolean(sharingValueParam);
&& Boolean.parseBoolean(sharingValueParam));
apiConfig.setSharedWithAllTenants(isSharedWithAllTenants); apiConfig.setSharedWithAllTenants(isSharedWithAllTenants);
Set<URITemplate> uriTemplates = new LinkedHashSet<>(); Set<URITemplate> uriTemplates = new LinkedHashSet<>();

@ -117,7 +117,7 @@ public interface Device {
*/ */
@GET @GET
@Path("user/{user}/count") @Path("user/{user}/count")
@Permission(scope = "device-count-own", permissions = { @Permission(scope = "device-view-own", permissions = {
"/permission/admin/device-mgt/user/devices/list", "/permission/admin/device-mgt/user/devices/list",
"/permission/admin/device-mgt/admin/devices/list"}) "/permission/admin/device-mgt/admin/devices/list"})
Response getDeviceCountOfUser(@PathParam("user") String user); Response getDeviceCountOfUser(@PathParam("user") String user);

@ -28,7 +28,7 @@ import javax.ws.rs.core.Response;
/** /**
* Features * Features
*/ */
@API(name = "Device Search", version = "1.0.0", context = "/devicemgt_admin/features", tags = {"devicemgt_admin"}) @API(name = "Feature", version = "1.0.0", context = "/devicemgt_admin/features", tags = {"devicemgt_admin"})
// Below Api is for swagger annotations // Below Api is for swagger annotations
@Api(value = "Feature", description = "Feature management related operations can be found here.") @Api(value = "Feature", description = "Feature management related operations can be found here.")
@ -58,7 +58,7 @@ public interface Feature {
@ApiResponses(value = { @ApiResponse(code = 200, message = "List of Features"), @ApiResponses(value = { @ApiResponse(code = 200, message = "List of Features"),
@ApiResponse(code = 500, message = "Error occurred while retrieving the list of features" + @ApiResponse(code = 500, message = "Error occurred while retrieving the list of features" +
".") }) ".") })
@Permission(scope = "device-search", permissions = {"/permission/admin/device-mgt/admin/devices/view", @Permission(scope = "feature-view", permissions = {"/permission/admin/device-mgt/admin/devices/view",
"/permission/admin/device-mgt/user/devices/view"}) "/permission/admin/device-mgt/user/devices/view"})
Response getFeatures(@ApiParam(name = "type", value = "Provide the device type, such as ios, android or windows", Response getFeatures(@ApiParam(name = "type", value = "Provide the device type, such as ios, android or windows",
required = true) @PathParam("type") String type); required = true) @PathParam("type") String type);

@ -146,7 +146,7 @@ public interface Role {
notes = "You are able to add a new role to WSO2 EMM using the REST API.") notes = "You are able to add a new role to WSO2 EMM using the REST API.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "Added the role."), @ApiResponses(value = { @ApiResponse(code = 200, message = "Added the role."),
@ApiResponse(code = 500, message = "Error occurred while adding the user role.") }) @ApiResponse(code = 500, message = "Error occurred while adding the user role.") })
@Permission(scope = "roles-modify", permissions = {"/permission/admin/device-mgt/admin/roles/add"}) @Permission(scope = "roles-add", permissions = {"/permission/admin/device-mgt/admin/roles/add"})
Response addRole(@ApiParam(name = "roleWrapper", value = "Role and permission details.", Response addRole(@ApiParam(name = "roleWrapper", value = "Role and permission details.",
required = true) RoleWrapper roleWrapper); required = true) RoleWrapper roleWrapper);
@ -180,7 +180,7 @@ public interface Role {
@ApiResponses(value = { @ApiResponse(code = 200, message = "Deleted the role."), @ApiResponses(value = { @ApiResponse(code = 200, message = "Deleted the role."),
@ApiResponse(code = 500, message = "Error occurred while deleting the user role details" + @ApiResponse(code = 500, message = "Error occurred while deleting the user role details" +
".") }) ".") })
@Permission(scope = "roles-modify", permissions = {"/permission/admin/device-mgt/admin/roles/remove"}) @Permission(scope = "roles-remove", permissions = {"/permission/admin/device-mgt/admin/roles/remove"})
Response deleteRole(@ApiParam(name = "rolename", value = "Provide the name of the role you wish to delete.", Response deleteRole(@ApiParam(name = "rolename", value = "Provide the name of the role you wish to delete.",
required = true) @QueryParam("rolename") String roleName); required = true) @QueryParam("rolename") String roleName);
@ -217,7 +217,7 @@ public interface Role {
notes = "Get the number of roles in WSO2 EMM.") notes = "Get the number of roles in WSO2 EMM.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "Retrieved the role count."), @ApiResponses(value = { @ApiResponse(code = 200, message = "Retrieved the role count."),
@ApiResponse(code = 500, message = "Error occurred while retrieving the role count.") }) @ApiResponse(code = 500, message = "Error occurred while retrieving the role count.") })
@Permission(scope = "roles-modify", permissions = {"/permission/admin/device-mgt/admin/roles/list"}) @Permission(scope = "roles-view", permissions = {"/permission/admin/device-mgt/admin/roles/list"})
Response getRoleCount(); Response getRoleCount();
} }

@ -52,7 +52,7 @@ public interface User {
@ApiResponse(code = 201, message = "Created"), @ApiResponse(code = 201, message = "Created"),
@ApiResponse(code = 500, message = "Exception in trying to add user by username: 'username'") @ApiResponse(code = 500, message = "Exception in trying to add user by username: 'username'")
}) })
@Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/user/add"}) @Permission(scope = "user-add", permissions = {"/permission/admin/device-mgt/admin/user/add"})
Response addUser(@ApiParam(name = "userWrapper", value = "Includes the required properties to add a user" Response addUser(@ApiParam(name = "userWrapper", value = "Includes the required properties to add a user"
+ " as the <JSON_PAYLOAD> value", required = true) UserWrapper userWrapper); + " as the <JSON_PAYLOAD> value", required = true) UserWrapper userWrapper);
@ -113,7 +113,7 @@ public interface User {
@ApiResponse(code = 400, message = "User by username: 'username' does not exist for removal"), @ApiResponse(code = 400, message = "User by username: 'username' does not exist for removal"),
@ApiResponse(code = 500, message = "Exception in trying to remove user by username: 'username'") @ApiResponse(code = 500, message = "Exception in trying to remove user by username: 'username'")
}) })
@Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/user/remove"}) @Permission(scope = "user-remove", permissions = {"/permission/admin/device-mgt/admin/user/remove"})
Response removeUser(@ApiParam(name = "username", value = "Provide the name of the user you wish to delete" Response removeUser(@ApiParam(name = "username", value = "Provide the name of the user you wish to delete"
+ " as the value for {username}", required = true) + " as the value for {username}", required = true)
@QueryParam("username") String username); @QueryParam("username") String username);
@ -220,7 +220,7 @@ public interface User {
@ApiResponse(code = 200, message = "Email invitation was successfully sent to user"), @ApiResponse(code = 200, message = "Email invitation was successfully sent to user"),
@ApiResponse(code = 500, message = "Error occurred while retrieving the list of users") @ApiResponse(code = 500, message = "Error occurred while retrieving the list of users")
}) })
@Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/users/invite"}) @Permission(scope = "user-invite", permissions = {"/permission/admin/device-mgt/admin/users/invite"})
Response inviteExistingUsersToEnrollDevice(@ApiParam(name = "usernames", value = "List of the users to be" Response inviteExistingUsersToEnrollDevice(@ApiParam(name = "usernames", value = "List of the users to be"
+ " invited as the <JSON_PAYLOAD>", required = true) + " invited as the <JSON_PAYLOAD>", required = true)
List<String> usernames); List<String> usernames);
@ -291,7 +291,7 @@ public interface User {
+ " Character Encoding is not supported"), + " Character Encoding is not supported"),
@ApiResponse(code = 500, message = "Internal Server Error") @ApiResponse(code = 500, message = "Internal Server Error")
}) })
@Permission(scope = "user-modify", permissions = {"/permission/admin/login"}) @Permission(scope = "user-password-modify", permissions = {"/permission/admin/login"})
Response resetPassword(@ApiParam(name = "credentials", value = "Include the required properties to change" Response resetPassword(@ApiParam(name = "credentials", value = "Include the required properties to change"
+ " the user password as <JSON_PAYLOAD> value", required = true) + " the user password as <JSON_PAYLOAD> value", required = true)
UserCredentialWrapper credentials); UserCredentialWrapper credentials);
@ -317,7 +317,7 @@ public interface User {
+ " Character Encoding is not supported"), + " Character Encoding is not supported"),
@ApiResponse(code = 500, message = "Internal Server Error") @ApiResponse(code = 500, message = "Internal Server Error")
}) })
@Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/users/password-reset"}) @Permission(scope = "user-password-reset", permissions = {"/permission/admin/device-mgt/admin/users/password-reset"})
Response resetPasswordByAdmin(@ApiParam(name = "credentials", value = "Include the required properties " Response resetPasswordByAdmin(@ApiParam(name = "credentials", value = "Include the required properties "
+ "to change a user password as <JSON_PAYLOAD> value", + "to change a user password as <JSON_PAYLOAD> value",
required = true) UserCredentialWrapper credentials); required = true) UserCredentialWrapper credentials);

@ -79,6 +79,10 @@
<param-name>managed-api-owner</param-name> <param-name>managed-api-owner</param-name>
<param-value>admin</param-value> <param-value>admin</param-value>
</context-param> </context-param>
<context-param>
<param-name>isSharedWithAllTenants</param-name>
<param-value>true</param-value>
</context-param>
<!-- Below configuration is used to redirect http requests to https --> <!-- Below configuration is used to redirect http requests to https -->
<security-constraint> <security-constraint>

@ -2,7 +2,7 @@
"appContext" : "/devicemgt/", "appContext" : "/devicemgt/",
"webAgentContext" : "/devicemgt-web-agent/", "webAgentContext" : "/devicemgt-web-agent/",
"apiContext" : "api", "apiContext" : "api",
"httpsURL" : "%https.ip%", "httpsURL" : "https://localhost:8243",
"httpURL" : "%http.ip%", "httpURL" : "%http.ip%",
"wssURL" : "%https.ip%", "wssURL" : "%https.ip%",
"wsURL" : "%http.ip%", "wsURL" : "%http.ip%",
@ -11,9 +11,9 @@
"iOSAPIRoot" : "%https.ip%/ios/", "iOSAPIRoot" : "%https.ip%/ios/",
"dynamicClientRegistrationEndPoint" : "%https.ip%/dynamic-client-web/register/", "dynamicClientRegistrationEndPoint" : "%https.ip%/dynamic-client-web/register/",
"adminService":"%https.ip%", "adminService":"%https.ip%",
"idPServer":"%https.ip%", "idPServer":"https://localhost:8243",
"callBackUrl":"%https.ip%/devicemgt_admin", "callBackUrl":"%https.ip%/devicemgt_admin",
"adminUser":"admin", "adminUser":"admin@carbon.super",
"adminRole":"admin", "adminRole":"admin",
"usernameLength":30, "usernameLength":30,
"ssoConfiguration" : { "ssoConfiguration" : {
@ -55,5 +55,12 @@
"copyrightOwner" : "WSO2 Inc.", "copyrightOwner" : "WSO2 Inc.",
"copyrightOwnersSite" : "http://www.wso2.org", "copyrightOwnersSite" : "http://www.wso2.org",
"copyrightSuffix" : " All Rights Reserved." "copyrightSuffix" : " All Rights Reserved."
} },
"scopes" : ["license-add", "license-view", "device-view", "device-info", "device-list", "device-view-own",
"device-modify", "device-search", "operation-install", "operation-view", "operation-modify", "operation-uninstall",
"group-add", "group-share", "group-modify", "group-view", "group-remove", "certificate-modify", "certificate-view",
"configuration-view", "configuration-modify", "policy-view", "policy-modify", "device-notification-view",
"device-notification-modify", "feature-view", "arduino_device", "arduino_user", " android_sense_user",
"virtual_firealarm_user", "raspberrypi_user", "roles-view", "roles-modify", "roles-remove", "roles-add",
"user-password-reset", "user-password-modify", "user-modify", "user-view", "user-invite", "user-remove", "user-add"]
} }

@ -20,7 +20,8 @@ var apiWrapperUtil = function () {
var module = {}; var module = {};
var tokenUtil = require("/app/modules/util.js").util; var tokenUtil = require("/app/modules/util.js").util;
var constants = require("/app/modules/constants.js"); var constants = require("/app/modules/constants.js");
var constants = require("/app/modules/constants.js"); var devicemgtProps = require('/app/conf/devicemgt-props.js').config();
var log = new Log("/app/modules/api-wrapper-util.js");
module.refreshToken = function () { module.refreshToken = function () {
var tokenPair = session.get(constants.ACCESS_TOKEN_PAIR_IDENTIFIER); var tokenPair = session.get(constants.ACCESS_TOKEN_PAIR_IDENTIFIER);
@ -31,11 +32,19 @@ var apiWrapperUtil = function () {
module.setupAccessTokenPair = function (type, properties) { module.setupAccessTokenPair = function (type, properties) {
var tokenPair; var tokenPair;
var clientData = tokenUtil.getDyanmicCredentials(properties); var clientData = tokenUtil.getDyanmicCredentials(properties);
var jwtToken = tokenUtil.getTokenWithJWTGrantType(clientData);
clientData = tokenUtil.getTenantBasedAppCredentials(properties.username, jwtToken);
var encodedClientKeys = tokenUtil.encode(clientData.clientId + ":" + clientData.clientSecret); var encodedClientKeys = tokenUtil.encode(clientData.clientId + ":" + clientData.clientSecret);
session.put(constants.ENCODED_CLIENT_KEYS_IDENTIFIER, encodedClientKeys); session.put(constants.ENCODED_CLIENT_KEYS_IDENTIFIER, encodedClientKeys);
if (type == constants.GRANT_TYPE_PASSWORD) { if (type == constants.GRANT_TYPE_PASSWORD) {
var scopes = devicemgtProps.scopes;
var scope = "";
scopes.forEach(function(entry) {
scope += entry + " ";
});
tokenPair = tokenPair =
tokenUtil.getTokenWithPasswordGrantType(properties.username, encodeURIComponent(properties.password), encodedClientKeys); tokenUtil.getTokenWithPasswordGrantType(properties.username, encodeURIComponent(properties.password),
encodedClientKeys, scope);
} else if (type == constants.GRANT_TYPE_SAML) { } else if (type == constants.GRANT_TYPE_SAML) {
tokenPair = tokenUtil. tokenPair = tokenUtil.
getTokenWithSAMLGrantType(properties.samlToken, encodedClientKeys, "PRODUCTION"); getTokenWithSAMLGrantType(properties.samlToken, encodedClientKeys, "PRODUCTION");

@ -65,6 +65,7 @@ var backendServiceInvoker = function () {
} }
xmlHttpRequest.setRequestHeader(constants.CONTENT_TYPE_IDENTIFIER, contentType); xmlHttpRequest.setRequestHeader(constants.CONTENT_TYPE_IDENTIFIER, contentType);
xmlHttpRequest.setRequestHeader(constants.ACCEPT_IDENTIFIER, acceptType); xmlHttpRequest.setRequestHeader(constants.ACCEPT_IDENTIFIER, acceptType);
xmlHttpRequest.setRequestHeader(constants.REFERER, String(privateMethods.getClientDomain()));
if (IS_OAUTH_ENABLED) { if (IS_OAUTH_ENABLED) {
var accessToken = privateMethods.getAccessToken(); var accessToken = privateMethods.getAccessToken();
if (!accessToken) { if (!accessToken) {
@ -150,6 +151,10 @@ var backendServiceInvoker = function () {
header.setName(constants.ACCEPT_IDENTIFIER); header.setName(constants.ACCEPT_IDENTIFIER);
header.setValue(acceptType); header.setValue(acceptType);
httpMethodObject.addRequestHeader(header); httpMethodObject.addRequestHeader(header);
header = new Header();
header.setName(constants.REFERER);
header.setValue(String(privateMethods.getClientDomain()));
httpMethodObject.addRequestHeader(header);
if (IS_OAUTH_ENABLED) { if (IS_OAUTH_ENABLED) {
var accessToken = privateMethods.getAccessToken(); var accessToken = privateMethods.getAccessToken();
if (accessToken) { if (accessToken) {
@ -210,6 +215,12 @@ var backendServiceInvoker = function () {
oAuthAuthenticationData.name = authenticationHeaderName; oAuthAuthenticationData.name = authenticationHeaderName;
oAuthAuthenticationData.value = authenticationHeaderValue; oAuthAuthenticationData.value = authenticationHeaderValue;
headers.push(oAuthAuthenticationData); headers.push(oAuthAuthenticationData);
var referrerData = {};
referrerData.name = constants.REFERER;
referrerData.value = String(privateMethods.getClientDomain());
headers.push(referrerData);
options.HTTPHeaders = headers; options.HTTPHeaders = headers;
} else { } else {
response.sendRedirect(devicemgtProps["httpsURL"] + "/devicemgt/login"); response.sendRedirect(devicemgtProps["httpsURL"] + "/devicemgt/login");
@ -331,6 +342,16 @@ var backendServiceInvoker = function () {
return privateMethods.initiateHTTPClientRequest(constants.HTTP_DELETE, url, successCallback, errorCallback, contentType, acceptType); return privateMethods.initiateHTTPClientRequest(constants.HTTP_DELETE, url, successCallback, errorCallback, contentType, acceptType);
}; };
/**
* This method fetch the current logged user from the session and returns
* the tenant domain name of the user
* @returns {tenantDomain}
*/
privateMethods.getClientDomain = function () {
var user = session.get(constants.USER_SESSION_KEY);
return user.domain;
}
var publicInvokers = {}; var publicInvokers = {};
publicInvokers.XMLHttp = publicXMLHTTPInvokers; publicInvokers.XMLHttp = publicXMLHTTPInvokers;
publicInvokers.WS = publicWSInvokers; publicInvokers.WS = publicWSInvokers;

@ -70,6 +70,7 @@ var HTTP_GET = "GET";
var HTTP_POST = "POST"; var HTTP_POST = "POST";
var HTTP_PUT = "PUT"; var HTTP_PUT = "PUT";
var HTTP_DELETE = "DELETE"; var HTTP_DELETE = "DELETE";
var REFERER = "referer"
var GRANT_TYPE_PASSWORD = "password"; var GRANT_TYPE_PASSWORD = "password";
var GRANT_TYPE_SAML = "saml"; var GRANT_TYPE_SAML = "saml";
@ -78,3 +79,5 @@ var MQTT_QUEUE_CONFIG_NAME = "MQTT";
var HTTP_CONFLICT = 409; var HTTP_CONFLICT = 409;
var HTTP_CREATED = 201; var HTTP_CREATED = 201;
var CACHED_CREDENTIALS = "tenantBasedCredentials";

@ -35,7 +35,7 @@ var onFail;
} }
var devicemgtProps = require('/app/conf/devicemgt-props.js').config(); var devicemgtProps = require('/app/conf/devicemgt-props.js').config();
var carbonServer = require("carbon").server; var carbonServer = require("carbon").server;
(new carbonServer.Server({url: devicemgtProps["httpsURL"]})) (new carbonServer.Server({url: devicemgtProps["adminService"]}))
.login(context.input.username, context.input.password); .login(context.input.username, context.input.password);
}; };

@ -23,16 +23,15 @@ var util = function () {
var String = Packages.java.lang.String; var String = Packages.java.lang.String;
var devicemgtProps = require('/app/conf/devicemgt-props.js').config(); var devicemgtProps = require('/app/conf/devicemgt-props.js').config();
var carbon = require('carbon'); var carbon = require('carbon');
var realmService = carbon.server.osgiService('org.wso2.carbon.user.core.service.RealmService');
var adminUserName = realmService.getBootstrapRealmConfiguration().getAdminUserName();
var constants = require("/app/modules/constants.js"); var constants = require("/app/modules/constants.js");
var adminUser = devicemgtProps["adminUser"];
module.getDyanmicCredentials = function (owner) { module.getDyanmicCredentials = function (owner) {
var payload = { var payload = {
"callbackUrl": devicemgtProps.callBackUrl, "callbackUrl": devicemgtProps.callBackUrl,
"clientName": "devicemgt", "clientName": "devicemgt",
"tokenScope": "admin", "tokenScope": "admin",
"owner": adminUserName, "owner": adminUser,
"applicationType": "webapp", "applicationType": "webapp",
"grantType": "password refresh_token urn:ietf:params:oauth:grant-type:saml2-bearer", "grantType": "password refresh_token urn:ietf:params:oauth:grant-type:saml2-bearer",
"saasApp" :true "saasApp" :true
@ -47,6 +46,7 @@ var util = function () {
var data = parse(xhr.responseText); var data = parse(xhr.responseText);
clientData.clientId = data.client_id; clientData.clientId = data.client_id;
clientData.clientSecret = data.client_secret; clientData.clientSecret = data.client_secret;
} else if (xhr.status == 400) { } else if (xhr.status == 400) {
throw "Invalid client meta data"; throw "Invalid client meta data";
} else { } else {
@ -79,7 +79,7 @@ var util = function () {
*/ */
module.getTokenWithPasswordGrantType = function (username, password, encodedClientKeys, scope) { module.getTokenWithPasswordGrantType = function (username, password, encodedClientKeys, scope) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
var tokenEndpoint = devicemgtProps.idPServer + "/oauth2/token"; var tokenEndpoint = devicemgtProps.idPServer + "/token";
xhr.open("POST", tokenEndpoint, false); xhr.open("POST", tokenEndpoint, false);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("Authorization", "Basic " + encodedClientKeys); xhr.setRequestHeader("Authorization", "Basic " + encodedClientKeys);
@ -137,6 +137,7 @@ var util = function () {
} }
return tokenPair; return tokenPair;
}; };
module.refreshToken = function (tokenPair, clientData, scope) { module.refreshToken = function (tokenPair, clientData, scope) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
var tokenEndpoint = devicemgtProps.idPServer + "/oauth2/token"; var tokenEndpoint = devicemgtProps.idPServer + "/oauth2/token";
@ -163,5 +164,62 @@ var util = function () {
} }
return tokenPair; return tokenPair;
}; };
module.getTokenWithJWTGrantType = function (clientData) {
var jwtService = carbon.server.osgiService('org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService');
var jwtClient = jwtService.getJWTClient();
var jwtToken = jwtClient.getAccessToken(clientData.clientId, clientData.clientSecret, adminUser, null);
return jwtToken;
};
module.getTenantBasedAppCredentials = function (uname, token) {
var tenantDomain = carbonModule.server.tenantDomain({
username: uname
});
var clientData = this.getCachedCredentials(tenantDomain);
if (!clientData) {
var applicationName = "webapp_" + tenantDomain;
var xhr = new XMLHttpRequest();
var endpoint = devicemgtProps["adminService"] + "/api-application-registration/register/tenants?tenantDomain=" +
tenantDomain + "&applicationName=" + applicationName;
xhr.open("POST", endpoint, false);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Authorization", "Bearer " + token.accessToken);
xhr.send();
if (xhr.status == 201) {
var data = parse(xhr.responseText);
clientData = {};
clientData.clientId = data.client_id;
clientData.clientSecret = data.client_secret;
this.setTenantBasedAppCredentials(tenantDomain, clientData);
} else if (xhr.status == 400) {
throw "Invalid client meta data";
} else {
throw "Error in obtaining client id and secret from APIM";
}
}
return clientData;
};
module.setTenantBasedAppCredentials = function (tenantDomain, clientData) {
var cachedMap = application.get(constants.CACHED_CREDENTIALS);
if (!cachedMap) {
cachedMap = new Object();
cachedMap[tenantDomain] = clientData;
application.put(constants.CACHED_CREDENTIALS, cachedMap);
} else {
cachedMap[tenantDomain] = clientData;
}
};
module.getCachedCredentials = function(tenantDomain) {
var cachedMap = application.get(constants.CACHED_CREDENTIALS);
if (cachedMap) {
return cachedMap[tenantDomain];
}
return null;
};
return module; return module;
}(); }();

@ -41,128 +41,128 @@ import java.util.concurrent.ConcurrentHashMap;
/** /**
* This creates JWT Client for each tenant and implements the JWTClientManagerService interface. * This creates JWT Client for each tenant and implements the JWTClientManagerService interface.
*/ */
public class JWTClientManagerServiceImpl implements JWTClientManagerService{ public class JWTClientManagerServiceImpl implements JWTClientManagerService {
private static Map<String, JWTClient> jwtClientMap; private static Map<String, JWTClient> jwtClientMap;
private static final Log log = LogFactory.getLog(JWTClientManagerServiceImpl.class); private static final Log log = LogFactory.getLog(JWTClientManagerServiceImpl.class);
private static final String TENANT_JWT_CONFIG_LOCATION = "/jwt-config/jwt.properties"; private static final String TENANT_JWT_CONFIG_LOCATION = "/jwt-config/jwt.properties";
private static JWTClient defaultJWTClient; private static JWTClient defaultJWTClient;
public JWTClientManagerServiceImpl() { public JWTClientManagerServiceImpl() {
jwtClientMap = new ConcurrentHashMap<>(); jwtClientMap = new ConcurrentHashMap<>();
} }
/** /**
* this return the jwt based token client to generate token for the tenant. * this return the jwt based token client to generate token for the tenant.
*/ */
@Override @Override
public JWTClient getJWTClient() throws JWTClientException { public JWTClient getJWTClient() throws JWTClientException {
String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain(); String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
if (tenantId == -1) { if (tenantId == -1) {
throw new JWTClientException("Invalid tenant domain :" + tenantDomain); throw new JWTClientException("Invalid tenant domain :" + tenantDomain);
} }
//Get jwt client which has been registered for the tenant. //Get jwt client which has been registered for the tenant.
JWTClient jwtClient = getJWTClient(tenantDomain); JWTClient jwtClient = getJWTClient(tenantDomain);
if (jwtClient == null) { if (jwtClient == null) {
//Create a new jwt client for the tenant. //Create a new jwt client for the tenant.
try { try {
Properties properties = getJWTConfigProperties(tenantId); Properties properties = getJWTConfigProperties(tenantId);
if (properties == null) { if (properties == null) {
if (defaultJWTClient != null) { if (defaultJWTClient != null) {
return defaultJWTClient; return defaultJWTClient;
} else { } else {
throw new JWTClientException("JWT Configuration is not available for tenant " + tenantDomain); throw new JWTClientException("JWT Configuration is not available for tenant " + tenantDomain);
} }
} }
JWTConfig jwtConfig = new JWTConfig(properties); JWTConfig jwtConfig = new JWTConfig(properties);
jwtClient = new JWTClient(jwtConfig); jwtClient = new JWTClient(jwtConfig);
addJWTClient(tenantDomain, jwtClient); addJWTClient(tenantDomain, jwtClient);
} catch (JWTClientAlreadyExistsException e) { } catch (JWTClientAlreadyExistsException e) {
log.warn("Attempting to register a jwt client for the tenant " + tenantDomain + log.warn("Attempting to register a jwt client for the tenant " + tenantDomain +
" when one already exists. Returning existing jwt client"); " when one already exists. Returning existing jwt client");
return getJWTClient(tenantDomain); return getJWTClient(tenantDomain);
} catch (JWTClientConfigurationException e) { } catch (JWTClientConfigurationException e) {
throw new JWTClientException("Failed to parse jwt configuration for tenant " + tenantDomain, e); throw new JWTClientException("Failed to parse jwt configuration for tenant " + tenantDomain, e);
} }
} }
return jwtClient; return jwtClient;
} }
/** /**
* This will set the default JWT Client that will be used if there is any available for tenants. * This will set the default JWT Client that will be used if there is any available for tenants.
*/ */
@Override @Override
public void setDefaultJWTClient(Properties properties) throws JWTClientConfigurationException { public void setDefaultJWTClient(Properties properties) throws JWTClientConfigurationException {
if (properties == null) { if (properties == null) {
throw new JWTClientConfigurationException("Failed to load jwt configuration for super tenant."); throw new JWTClientConfigurationException("Failed to load jwt configuration for super tenant.");
} }
String defaultJWTClientMode = properties.getProperty(JWTConstants.DEFAULT_JWT_CLIENT); String defaultJWTClientMode = properties.getProperty(JWTConstants.DEFAULT_JWT_CLIENT);
boolean isDefaultJwtClient = false; boolean isDefaultJwtClient = false;
if (defaultJWTClientMode != null && !defaultJWTClientMode.isEmpty()) { if (defaultJWTClientMode != null && !defaultJWTClientMode.isEmpty()) {
isDefaultJwtClient = Boolean.parseBoolean(defaultJWTClientMode); isDefaultJwtClient = Boolean.parseBoolean(defaultJWTClientMode);
} }
if (isDefaultJwtClient) { if (isDefaultJwtClient) {
try { try {
JWTConfig jwtConfig = new JWTConfig(properties); JWTConfig jwtConfig = new JWTConfig(properties);
defaultJWTClient = new JWTClient(jwtConfig, true); defaultJWTClient = new JWTClient(jwtConfig, true);
addJWTClient(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, defaultJWTClient); addJWTClient(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, defaultJWTClient);
} catch (JWTClientAlreadyExistsException e) { } catch (JWTClientAlreadyExistsException e) {
log.warn("Attempting to register a jwt client for the super tenant" + log.warn("Attempting to register a jwt client for the super tenant" +
" when one already exists. Returning existing jwt client"); " when one already exists. Returning existing jwt client");
} }
} }
} }
/** /**
* Fetch the jwt client which has been registered under the tenant domain. * Fetch the jwt client which has been registered under the tenant domain.
* *
* @param tenantDomain - The tenant domain under which the jwt client is registered * @param tenantDomain - The tenant domain under which the jwt client is registered
* @return - Instance of the jwt client which was registered. Null if not registered. * @return - Instance of the jwt client which was registered. Null if not registered.
*/ */
private JWTClient getJWTClient(String tenantDomain) { private JWTClient getJWTClient(String tenantDomain) {
if (jwtClientMap.containsKey(tenantDomain)) { if (jwtClientMap.containsKey(tenantDomain)) {
return jwtClientMap.get(tenantDomain); return jwtClientMap.get(tenantDomain);
} }
return null; return null;
} }
/** /**
* Adds a jwt client to the jwt client map. * Adds a jwt client to the jwt client map.
* *
* @param tenantDomain - The tenant domain under which the jwt client will be registered. * @param tenantDomain - The tenant domain under which the jwt client will be registered.
* @param jwtClient - Instance of the jwt client * @param jwtClient - Instance of the jwt client
* @throws JWTClientAlreadyExistsException - If a jwt client has already been registered under the tenantdomain * @throws JWTClientAlreadyExistsException - If a jwt client has already been registered under the tenantdomain
*/ */
private void addJWTClient(String tenantDomain, JWTClient jwtClient) throws JWTClientAlreadyExistsException { private void addJWTClient(String tenantDomain, JWTClient jwtClient) throws JWTClientAlreadyExistsException {
synchronized (jwtClientMap) { synchronized (jwtClientMap) {
if (jwtClientMap.containsKey(tenantDomain)) { if (jwtClientMap.containsKey(tenantDomain)) {
throw new JWTClientAlreadyExistsException( throw new JWTClientAlreadyExistsException(
"A jwt client has already been created for the tenant " + tenantDomain); "A jwt client has already been created for the tenant " + tenantDomain);
} }
jwtClientMap.put(tenantDomain, jwtClient); jwtClientMap.put(tenantDomain, jwtClient);
} }
} }
/** /**
* Retrieve JWT configs from registry. * Retrieve JWT configs from registry.
*/ */
private Properties getJWTConfigProperties(int tenantId) throws JWTClientConfigurationException { private Properties getJWTConfigProperties(int tenantId) throws JWTClientConfigurationException {
try { try {
Resource config = JWTClientUtil.getConfigRegistryResourceContent(tenantId, TENANT_JWT_CONFIG_LOCATION); Resource config = JWTClientUtil.getConfigRegistryResourceContent(tenantId, TENANT_JWT_CONFIG_LOCATION);
Properties properties = null; Properties properties = null;
if (config != null) { if (config != null) {
properties = new Properties(); properties = new Properties();
properties.load(config.getContentStream()); properties.load(config.getContentStream());
} }
return properties; return properties;
} catch (RegistryException e) { } catch (RegistryException e) {
throw new JWTClientConfigurationException("Failed to load the content from registry for tenant " + throw new JWTClientConfigurationException("Failed to load the content from registry for tenant " +
tenantId, e); tenantId, e);
} catch (IOException e) { } catch (IOException e) {
throw new JWTClientConfigurationException( throw new JWTClientConfigurationException(
"Failed to parse the content from the registry for tenant " + tenantId, e); "Failed to parse the content from the registry for tenant " + tenantId, e);
} }
} }
} }

@ -26,6 +26,8 @@ import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response; import org.apache.catalina.connector.Response;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.util.KeyStoreManager; import org.wso2.carbon.core.util.KeyStoreManager;
import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.service.TenantRegistryLoader; import org.wso2.carbon.registry.core.service.TenantRegistryLoader;
@ -88,12 +90,23 @@ public class JWTAuthenticator implements WebappAuthenticator {
String username = jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_USERNAME); String username = jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_USERNAME);
String tenantDomain = MultitenantUtils.getTenantDomain(username); String tenantDomain = MultitenantUtils.getTenantDomain(username);
int tenantId = Integer.parseInt(jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_TENANT_ID)); int tenantId = Integer.parseInt(jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_TENANT_ID));
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId);
PublicKey publicKey = publicKeyHolder.get(tenantDomain); PublicKey publicKey = publicKeyHolder.get(tenantDomain);
if (publicKey == null) { if (publicKey == null) {
loadTenantRegistry(tenantId); loadTenantRegistry(tenantId);
KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(tenantId); KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(tenantId);
publicKey = keyStoreManager.getDefaultPublicKey(); if (tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
publicKeyHolder.put(tenantDomain, publicKey); publicKey = keyStoreManager.getDefaultPublicKey();
} else {
String ksName = tenantDomain.trim().replace('.', '-');
String jksName = ksName + ".jks";
publicKey = keyStoreManager.getKeyStore(jksName).getCertificate(tenantDomain).getPublicKey();
}
if (publicKey != null) {
publicKeyHolder.put(tenantDomain, publicKey);
}
} }
//Get the filesystem keystore default primary certificate //Get the filesystem keystore default primary certificate
@ -124,6 +137,8 @@ public class JWTAuthenticator implements WebappAuthenticator {
log.error("Error occurred while verifying the JWT header.", e); log.error("Error occurred while verifying the JWT header.", e);
} catch (Exception e) { } catch (Exception e) {
log.error("Error occurred while verifying the JWT header.", e); log.error("Error occurred while verifying the JWT header.", e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
} }
return authenticationInfo; return authenticationInfo;
} }

Loading…
Cancel
Save