Merge pull request 'Fix dcr and token endpoint related issues' (#9) from vigneshan/device-mgt-core:fix/key-mgt-api into master

Reviewed-on: community/device-mgt-core#9
fix/key-mgt-api
Pahansith Gunathilake 2 years ago
commit bd9aa0ea5c

@ -49,6 +49,7 @@ public class APIUtil {
private static final String DEFAULT_ANALYTICS_ARTIFACT_TAG = "analytics_artifacts_management";
private static final String DEFAULT_TRANSPORT_MGT_TAG = "transport_management";
private static final String DEFAULT_ENTERPRISE_TAG= "androidforwork";
private static final String DEFAULT_ANALYTICS_MGT_TAG= "analytics_management";
public static final String PERMISSION_PROPERTY_NAME = "name";
@ -119,6 +120,7 @@ public class APIUtil {
allowedApisTags.add(DEFAULT_APP_MGT_SUB_MGT_TAG);
allowedApisTags.add(DEFAULT_ANALYTICS_ARTIFACT_TAG);
allowedApisTags.add(DEFAULT_TRANSPORT_MGT_TAG);
allowedApisTags.add(DEFAULT_ANALYTICS_MGT_TAG);
// In an environment only super tenant should be capable of calling this API tag
if (PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId() ==
MultitenantConstants.SUPER_TENANT_ID) {

@ -28,9 +28,9 @@ import javax.xml.bind.annotation.XmlRootElement;
@JsonIgnoreProperties(ignoreUnknown = true)
public class DCRRequest {
@XmlElement(required = true)
private String clientName;
private String applicationName;
@XmlElement(required = true)
private String owner;
private String username;
@XmlElement(required = true)
private String grantTypes;
@XmlElement
@ -40,20 +40,20 @@ public class DCRRequest {
@XmlElement
private boolean isSaasApp;
public String getClientName() {
return clientName;
public String getApplicationName() {
return applicationName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public String getOwner() {
return owner;
public String getUsername() {
return username;
}
public void setOwner(String owner) {
this.owner = owner;
public void setUsername(String username) {
this.username = username;
}
public String getGrantTypes() {

@ -20,6 +20,7 @@ package org.wso2.carbon.apimgt.keymgt.extension.api;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@ -38,9 +39,12 @@ public interface KeyManagerService {
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/token")
Response generateAccessToken(@FormParam("client_id") String clientId,
Response generateAccessToken(@HeaderParam("Authorization") String basicAuthHeader,
@FormParam("client_id") String clientId,
@FormParam("client_secret") String clientSecret,
@FormParam("refresh_token") String refreshToken,
@FormParam("scope") String scope,
@FormParam("grant_type") String grantType);
@FormParam("grant_type") String grantType,
@FormParam("assertion") String assertion,
@FormParam("admin_access_token") String admin_access_token);
}

@ -27,14 +27,17 @@ import org.wso2.carbon.apimgt.keymgt.extension.exception.BadRequestException;
import org.wso2.carbon.apimgt.keymgt.extension.exception.KeyMgtException;
import org.wso2.carbon.apimgt.keymgt.extension.service.KeyMgtService;
import org.wso2.carbon.apimgt.keymgt.extension.service.KeyMgtServiceImpl;
import org.wso2.carbon.device.mgt.common.exceptions.UnAuthorizedException;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Base64;
public class KeyManagerServiceImpl implements KeyManagerService {
@ -46,7 +49,7 @@ public class KeyManagerServiceImpl implements KeyManagerService {
public Response dynamicClientRegistration(DCRRequest dcrRequest) {
try {
KeyMgtService keyMgtService = new KeyMgtServiceImpl();
DCRResponse resp = keyMgtService.dynamicClientRegistration(dcrRequest.getClientName(), dcrRequest.getOwner(),
DCRResponse resp = keyMgtService.dynamicClientRegistration(dcrRequest.getApplicationName(), dcrRequest.getUsername(),
dcrRequest.getGrantTypes(), dcrRequest.getCallBackUrl(), dcrRequest.getTags(), dcrRequest.getIsSaasApp());
return Response.status(Response.Status.CREATED).entity(resp).build();
} catch (KeyMgtException e) {
@ -58,20 +61,32 @@ public class KeyManagerServiceImpl implements KeyManagerService {
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/token")
public Response generateAccessToken(@FormParam("client_id") String clientId,
public Response generateAccessToken(@HeaderParam("Authorization") String basicAuthHeader,
@FormParam("client_id") String clientId,
@FormParam("client_secret") String clientSecret,
@FormParam("refresh_token") String refreshToken,
@FormParam("scope") String scope,
@FormParam("grant_type") String grantType) {
@FormParam("grant_type") String grantType,
@FormParam("assertion") String assertion,
@FormParam("admin_access_token") String admin_access_token) {
try {
if (basicAuthHeader == null) {
String msg = "Invalid credentials. Make sure your API call is invoked with a Basic Authorization header.";
throw new UnAuthorizedException(msg);
}
String encodedClientCredentials = new String(Base64.getDecoder().decode(basicAuthHeader.split(" ")[1]));
KeyMgtService keyMgtService = new KeyMgtServiceImpl();
TokenResponse resp = keyMgtService.generateAccessToken(
new TokenRequest(clientId, clientSecret, refreshToken, scope, grantType));
new TokenRequest(encodedClientCredentials.split(":")[0],
encodedClientCredentials.split(":")[1], refreshToken, scope,
grantType, assertion,admin_access_token));
return Response.status(Response.Status.CREATED).entity(resp).build();
} catch (KeyMgtException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (UnAuthorizedException e) {
return Response.status(Response.Status.UNAUTHORIZED).entity(e.getMessage()).build();
}
}
}

@ -19,27 +19,27 @@
package org.wso2.carbon.apimgt.keymgt.extension;
public class DCRResponse {
String clientId;
String clientSecret;
String client_id;
String client_secret;
public DCRResponse(String clientId, String clientSecret) {
this.clientId = clientId;
this.clientSecret = clientSecret;
public DCRResponse(String client_id, String client_secret) {
this.client_id = client_id;
this.client_secret = client_secret;
}
public String getClientId() {
return clientId;
return client_id;
}
public void setClientId(String clientId) {
this.clientId = clientId;
public void setClientId(String client_id) {
this.client_id = client_id;
}
public String getClientSecret() {
return clientSecret;
return client_secret;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
public void setClientSecret(String client_secret) {
this.client_secret = client_secret;
}
}

@ -24,13 +24,18 @@ public class TokenRequest {
private String refreshToken;
private String scope;
private String grantType;
private String assertion;
private String admin_access_token;
public TokenRequest(String clientId, String clientSecret, String refreshToken, String scope, String grantType) {
public TokenRequest(String clientId, String clientSecret, String refreshToken, String scope, String grantType,
String assertion, String admin_access_token) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.refreshToken = refreshToken;
this.scope = scope;
this.grantType = grantType;
this.assertion = assertion;
this.admin_access_token = admin_access_token;
}
public String getClientId() {
@ -72,4 +77,20 @@ public class TokenRequest {
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public String getAssertion() {
return assertion;
}
public void setAssertion(String assertion) {
this.assertion = assertion;
}
public String getAdminAccessToken() {
return admin_access_token;
}
public void setAdminAccessToken(String admin_access_token) {
this.admin_access_token = admin_access_token;
}
}

@ -22,14 +22,14 @@ public class TokenResponse {
private String access_token;
private String refresh_token;
private String scope;
private String tokenType;
private String token_type;
private int expires_in;
public TokenResponse(String access_token, String refresh_token, String scope, String tokenType, int expires_in) {
public TokenResponse(String access_token, String refresh_token, String scope, String token_type, int expires_in) {
this.access_token = access_token;
this.refresh_token = refresh_token;
this.scope = scope;
this.tokenType = tokenType;
this.token_type = token_type;
this.expires_in = expires_in;
}
@ -57,12 +57,12 @@ public class TokenResponse {
this.scope = scope;
}
public String getTokenType() {
return tokenType;
public String getToken_Type() {
return token_type;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
public void setTokenType(String token_type) {
this.token_type = token_type;
}
public int getExpiresIn() {

@ -20,6 +20,7 @@ package org.wso2.carbon.apimgt.keymgt.extension.service;
import com.google.gson.Gson;
import okhttp3.Credentials;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
@ -41,7 +42,6 @@ import org.wso2.carbon.apimgt.keymgt.extension.KeyMgtConstants;
import org.wso2.carbon.apimgt.keymgt.extension.OAuthApplication;
import org.wso2.carbon.apimgt.keymgt.extension.TokenRequest;
import org.wso2.carbon.apimgt.keymgt.extension.TokenResponse;
import org.wso2.carbon.apimgt.keymgt.extension.exception.BadRequestException;
import org.wso2.carbon.apimgt.keymgt.extension.exception.KeyMgtException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
@ -53,9 +53,7 @@ import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
@ -82,6 +80,17 @@ public class KeyMgtServiceImpl implements KeyMgtService {
public DCRResponse dynamicClientRegistration(String clientName, String owner, String grantTypes, String callBackUrl,
String[] tags, boolean isSaasApp) throws KeyMgtException {
if (owner == null) {
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
try {
owner = APIUtil.getTenantAdminUserName(threadLocalCarbonContext.getTenantDomain());
} catch (APIManagementException e) {
String msg = "Error occurred while retrieving admin user for the tenant " + threadLocalCarbonContext.getTenantDomain();
log.error(msg, e);
throw new KeyMgtException(msg);
}
}
String tenantDomain = MultitenantUtils.getTenantDomain(owner);
int tenantId;
@ -97,10 +106,8 @@ public class KeyMgtServiceImpl implements KeyMgtService {
kmConfig = getKeyManagerConfig();
if (KeyMgtConstants.SUPER_TENANT.equals(tenantDomain)) {
OAuthApplication superTenantOauthApp = createOauthApplication(
KeyMgtConstants.RESERVED_OAUTH_APP_NAME_PREFIX + KeyMgtConstants.SUPER_TENANT,
kmConfig.getAdminUsername(), tags);
return new DCRResponse(superTenantOauthApp.getClientId(), superTenantOauthApp.getClientSecret());
OAuthApplication dcrApplication = createOauthApplication(clientName, kmConfig.getAdminUsername(), tags);
return new DCRResponse(dcrApplication.getClientId(), dcrApplication.getClientSecret());
} else {
// super-tenant admin dcr and token generation
OAuthApplication superTenantOauthApp = createOauthApplication(
@ -141,7 +148,7 @@ public class KeyMgtServiceImpl implements KeyMgtService {
}
}
public TokenResponse generateAccessToken(TokenRequest tokenRequest) throws KeyMgtException, BadRequestException {
public TokenResponse generateAccessToken(TokenRequest tokenRequest) throws KeyMgtException {
try {
Application application = APIUtil.getApplicationByClientId(tokenRequest.getClientId());
String tenantDomain = MultitenantUtils.getTenantDomain(application.getOwner());
@ -167,20 +174,43 @@ public class KeyMgtServiceImpl implements KeyMgtService {
}
JSONObject jsonObject = new JSONObject();
if ("client_credentials".equals(tokenRequest.getGrantType())) {
jsonObject.put("grant_type", "password");
jsonObject.put("username", username);
jsonObject.put("password", password);
} else if ("refresh_token".equals(tokenRequest.getGrantType())) {
jsonObject.put("grant_type", "refresh_token");
jsonObject.put("refresh_token", tokenRequest.getRefreshToken());
} else {
msg = "Invalid grant type: " + tokenRequest.getGrantType();
throw new BadRequestException(msg);
RequestBody appTokenPayload;
switch (tokenRequest.getGrantType()) {
case "client_credentials":
case "password":
appTokenPayload = new FormBody.Builder()
.add("grant_type", "password")
.add("username", username)
.add("password", password)
.add("scope", tokenRequest.getScope()).build();
break;
case "refresh_token":
appTokenPayload = new FormBody.Builder()
.add("grant_type", "refresh_token")
.add("refresh_token", tokenRequest.getRefreshToken())
.add("scope", tokenRequest.getScope()).build();
break;
case "urn:ietf:params:oauth:grant-type:jwt-bearer":
appTokenPayload = new FormBody.Builder()
.add("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer")
.add("assertion", tokenRequest.getAssertion())
.add("scope", tokenRequest.getScope()).build();
break;
case "access_token":
appTokenPayload = new FormBody.Builder()
.add("grant_type", "access_token")
.add("admin_access_token", tokenRequest.getAdminAccessToken())
.add("scope", tokenRequest.getScope()).build();
break;
default:
appTokenPayload = new FormBody.Builder()
.add("grant_type", tokenRequest.getGrantType())
.add("scope", tokenRequest.getScope()).build();
break;
}
jsonObject.put("scope", tokenRequest.getScope());
RequestBody appTokenPayload = RequestBody.Companion.create(jsonObject.toString(), JSON);
kmConfig = getKeyManagerConfig();
String appTokenEndpoint = kmConfig.getServerUrl() + KeyMgtConstants.OAUTH2_TOKEN_ENDPOINT;
Request request = new Request.Builder()
@ -449,12 +479,7 @@ public class KeyMgtServiceImpl implements KeyMgtService {
};
return new OkHttpClient.Builder()
.sslSocketFactory(getSimpleTrustedSSLSocketFactory(), trustAllCerts)
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
}).build();
.hostnameVerifier((hostname, sslSession) -> true).build();
}
private static SSLSocketFactory getSimpleTrustedSSLSocketFactory() {

@ -1,3 +1,4 @@
instructions.configure = \
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/webapps/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.apimgt.keymgt.extension_${feature.version}/webapps/api-key-management.war,target:${installFolder}/../../deployment/server/webapps/api-key-management.war,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.apimgt.keymgt.extension_${feature.version}/synapse-configs/default/api/_API_Key_Management_.xml,target:${installFolder}/../../deployment/server/synapse-configs/default/api/_API_Key_Management_.xml,overwrite:true);\

@ -0,0 +1,46 @@
<!--
~ /*
~ * Copyright (c) 2022, 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.
~ */
~
-->
<api xmlns="http://ws.apache.org/ns/synapse" name="_API_Key_Management_" context="/api-application-registration/register">
<resource methods="POST" url-mapping="" 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-key-management/dynamic-client-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"/>
</handlers>
</api>
Loading…
Cancel
Save