diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/pom.xml b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/pom.xml
new file mode 100644
index 0000000000..965bf90b0b
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/pom.xml
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+ org.wso2.carbon.devicemgt
+ identity-extensions
+ 1.1.0-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ org.wso2.carbon.identity.jwt.client.extension
+ bundle
+ WSO2 Carbon - Device Management JWT Client Extensions
+ WSO2 Carbon - Device Management JWT Client Extensions
+ http://wso2.org
+
+
+
+ org.wso2.carbon.governance
+ org.wso2.carbon.governance.api
+
+
+ org.wso2.carbon
+ org.wso2.carbon.registry.api
+
+
+ org.wso2.carbon
+ org.wso2.carbon.registry.core
+
+
+ org.wso2.carbon.devicemgt
+ org.wso2.carbon.device.mgt.common
+
+
+ org.apache.ws.commons.axiom
+ axiom-api
+
+
+ org.wso2.carbon
+ org.wso2.carbon.utils
+
+
+ org.wso2.orbit.org.scannotation
+ scannotation
+
+
+ org.eclipse.osgi
+ org.eclipse.osgi
+
+
+ org.eclipse.osgi
+ org.eclipse.osgi.services
+
+
+ org.wso2.tomcat
+ tomcat
+
+
+ org.wso2.tomcat
+ tomcat-servlet-api
+
+
+ javax.ws.rs
+ jsr311-api
+
+
+ org.apache.axis2.wso2
+ axis2
+
+
+ commons-lang.wso2
+ commons-lang
+
+
+ org.wso2.carbon.analytics
+ org.wso2.carbon.analytics.api
+
+
+ org.wso2.carbon.registry
+ org.wso2.carbon.registry.indexing
+
+
+ org.wso2.orbit.com.nimbusds
+ nimbus-jose-jwt
+
+
+ com.googlecode.json-simple.wso2
+ json-simple
+
+
+ org.apache.httpcomponents.wso2
+ httpcore
+
+
+ org.wso2.orbit.org.apache.httpcomponents
+ httpclient
+
+
+
+
+
+
+ org.apache.felix
+ maven-scr-plugin
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ 1.4.0
+ true
+
+
+ ${project.artifactId}
+ ${project.artifactId}
+ ${carbon.device.mgt.version}
+ Device Management JWT Client Bundle
+ org.wso2.carbon.device.mgt.jwt.client.extension.internal
+
+ !org.wso2.carbon.device.mgt.jwt.client.extension.internal,
+ org.wso2.carbon.device.mgt.jwt.client.extension.*
+
+
+ org.osgi.framework,
+ org.osgi.service.component,
+ org.wso2.carbon.governance.api.*,
+ org.wso2.carbon.context,
+ org.wso2.carbon.registry.core,
+ org.wso2.carbon.registry.core.exceptions,
+ org.wso2.carbon.registry.core.session,
+ org.wso2.carbon.utils,
+ org.apache.commons.logging,
+ org.wso2.carbon.registry.core.*;resolution:=optional,
+ org.wso2.carbon.registry.common.*;version="${carbon.registry.imp.pkg.version.range}",
+ org.wso2.carbon.registry.indexing.*; version="${carbon.registry.imp.pkg.version.range}",
+ com.nimbusds.jwt.*;version="${nimbus.orbit.version.range}",
+ com.nimbusds.jose.*;version="${nimbus.orbit.version.range}",
+ javax.net.ssl,
+ org.apache.commons.codec.binary,
+ org.apache.commons.io,
+ org.apache.http;version="${httpclient.version.range}",
+ org.apache.http.client;version="${httpclient.version.range}",
+ org.apache.http.message;version="${httpclient.version.range}",
+ org.apache.http.client;version="${httpclient.version.range}",
+ org.apache.http.impl;version="${httpclient.version.range}",
+ org.apache.http.conn.*;version="${httpclient.version.range}",
+ org.apache.http.util;version="${httpclient.version.range}",
+ org.apache.http.client.entity;version="${httpclient.version.range}",
+ org.apache.http.client.methods;version="${httpclient.version.range}",
+ org.apache.http.impl.client;version="${httpclient.version.range}",
+ org.json.simple.*,
+ org.wso2.carbon.core.util,
+ javax.net.ssl,
+ org.wso2.carbon.user.core.service,
+ org.wso2.carbon.user.core.tenant
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClient.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClient.java
new file mode 100644
index 0000000000..0aa903d29a
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClient.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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 org.wso2.carbon.device.mgt.jwt.client.extension;
+
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.JWSHeader;
+import com.nimbusds.jose.JWSSigner;
+import com.nimbusds.jose.crypto.RSASSASigner;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.SignedJWT;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.message.BasicNameValuePair;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.core.util.KeyStoreManager;
+import org.wso2.carbon.device.mgt.jwt.client.extension.constant.JWTConstants;
+import org.wso2.carbon.device.mgt.jwt.client.extension.dto.AccessTokenInfo;
+import org.wso2.carbon.device.mgt.jwt.client.extension.dto.JWTConfig;
+import org.wso2.carbon.device.mgt.jwt.client.extension.exception.JWTClientException;
+import org.wso2.carbon.device.mgt.jwt.client.extension.util.JWTClientUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.interfaces.RSAPrivateKey;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * this class represents an implementation of Token Client which is based on JWT
+ */
+public class JWTClient {
+
+ private static Log log = LogFactory.getLog(JWTClient.class);
+ private static final String JWT_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer";
+ private static final String GRANT_TYPE_PARAM_NAME = "grant_type";
+ private static final String REFRESH_TOKEN_GRANT_TYPE = "refresh_token";
+ private static final String REFRESH_TOKEN_GRANT_TYPE_PARAM_NAME = "refresh_token";
+ private static final String JWT_PARAM_NAME = "assertion";
+ private static final String SCOPE_PARAM_NAME = "scope";
+ private JWTConfig jwtConfig;
+
+ public JWTClient(JWTConfig jwtConfig) {
+ this.jwtConfig = jwtConfig;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public AccessTokenInfo getAccessToken(String consumerKey, String consumerSecret, String username, String scopes)
+ throws JWTClientException {
+ List params = new ArrayList<>();
+ params.add(new BasicNameValuePair(GRANT_TYPE_PARAM_NAME, JWT_GRANT_TYPE));
+ String assertion = generateSignedJWTAssertion(username);
+ if (assertion == null) {
+ throw new JWTClientException("JWT is not configured properly for user : " + username);
+ }
+ params.add(new BasicNameValuePair(JWT_PARAM_NAME, assertion));
+ params.add(new BasicNameValuePair(SCOPE_PARAM_NAME, scopes));
+ return getTokenInfo(params, consumerKey, consumerSecret);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public AccessTokenInfo getAccessTokenFromRefreshToken(String refreshToken, String username, String scopes,
+ String consumerKey, String consumerSecret)
+ throws JWTClientException {
+ List params = new ArrayList<>();
+ params.add(new BasicNameValuePair(GRANT_TYPE_PARAM_NAME, REFRESH_TOKEN_GRANT_TYPE));
+ params.add(new BasicNameValuePair(REFRESH_TOKEN_GRANT_TYPE_PARAM_NAME, refreshToken));
+ params.add(new BasicNameValuePair(SCOPE_PARAM_NAME, scopes));
+ return getTokenInfo(params, consumerKey, consumerSecret);
+ }
+
+
+ private AccessTokenInfo getTokenInfo(List nameValuePairs, String consumerKey, String consumerSecret)
+ throws JWTClientException {
+ String response = null;
+ try {
+ if (jwtConfig == null) {
+ return null;
+ }
+ URL tokenEndpoint = new URL(jwtConfig.getTokenEndpoint());
+ HttpClient httpClient = JWTClientUtil.getHttpClient(tokenEndpoint.getProtocol());
+ HttpPost postMethod = new HttpPost(tokenEndpoint.toString());
+ postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs));
+ postMethod.addHeader("Authorization", "Basic " + getBase64Encode(consumerKey, consumerSecret));
+ postMethod.addHeader("Content-Type", "application/x-www-form-urlencoded");
+ HttpResponse httpResponse = httpClient.execute(postMethod);
+ response = JWTClientUtil.getResponseString(httpResponse);
+ if (log.isDebugEnabled()) {
+ log.debug(response);
+ }
+ JSONParser jsonParser = new JSONParser();
+ JSONObject jsonObject = (JSONObject) jsonParser.parse(response);
+ AccessTokenInfo accessTokenInfo = new AccessTokenInfo();
+ accessTokenInfo.setAccess_token((String) jsonObject.get(JWTConstants.OAUTH_ACCESS_TOKEN));
+ accessTokenInfo.setRefresh_token((String) jsonObject.get(JWTConstants.OAUTH_REFRESH_TOKEN));
+ accessTokenInfo.setExpires_in((Long) jsonObject.get(JWTConstants.OAUTH_EXPIRES_IN));
+ accessTokenInfo.setToken_type((String) jsonObject.get(JWTConstants.OAUTH_TOKEN_TYPE));
+ return accessTokenInfo;
+ } catch (MalformedURLException e) {
+ throw new JWTClientException("Invalid URL for token endpoint " + jwtConfig.getTokenEndpoint(), e);
+ } catch (ParseException e) {
+ throw new JWTClientException("Error when parsing the response " + response, e);
+ } catch (IOException e) {
+ throw new JWTClientException("Error when reading the response from buffer.", e);
+ } catch (NoSuchAlgorithmException e) {
+ throw new JWTClientException("No such algorithm found when loading the ssl socket", e);
+ } catch (KeyStoreException e) {
+ throw new JWTClientException("Failed loading the keystore.", e);
+ } catch (KeyManagementException e) {
+ throw new JWTClientException("Failed setting up the ssl http client.", e);
+ }
+ }
+
+ private String getBase64Encode(String consumerKey, String consumerSecret) {
+ return new String(Base64.encodeBase64((consumerKey + ":" + consumerSecret).getBytes()));
+ }
+
+ public String generateSignedJWTAssertion(String username) throws JWTClientException {
+ try {
+ String subject = username;
+ long currentTimeMillis = System.currentTimeMillis();
+ // add the skew between servers
+ String iss = jwtConfig.getIssuer();
+ if (iss == null || iss.isEmpty()) {
+ return null;
+ }
+ currentTimeMillis += jwtConfig.getSkew();
+ long iat = currentTimeMillis + jwtConfig.getIssuedInternal() * 60 * 1000;
+ long exp = currentTimeMillis + jwtConfig.getExpirationTime() * 60 * 1000;
+ long nbf = currentTimeMillis + jwtConfig.getValidityPeriodFromCurrentTime() * 60 * 1000;
+ String jti = jwtConfig.getJti();
+ if (jti == null) {
+ String defaultTokenId = currentTimeMillis + "" + new Random().nextInt();
+ jti = defaultTokenId;
+ }
+ List aud = jwtConfig.getAudiences();
+ //set up the basic claims
+ JWTClaimsSet claimsSet = new JWTClaimsSet();
+ claimsSet.setIssueTime(new Date(iat));
+ claimsSet.setExpirationTime(new Date(exp));
+ claimsSet.setIssuer(iss);
+ claimsSet.setSubject(username);
+ claimsSet.setNotBeforeTime(new Date(nbf));
+ claimsSet.setJWTID(jti);
+ claimsSet.setAudience(aud);
+
+ // get Keystore params
+ String keyStorePath = jwtConfig.getKeyStorePath();
+ String privateKeyAlias = jwtConfig.getPrivateKeyAlias();
+ String privateKeyPassword = jwtConfig.getPrivateKeyPassword();
+ KeyStore keyStore;
+ RSAPrivateKey rsaPrivateKey;
+ if (keyStorePath != null && !keyStorePath.isEmpty()) {
+ String keyStorePassword = jwtConfig.getKeyStorePassword();
+ keyStore = loadKeyStore(new File(keyStorePath), keyStorePassword, "JKS");
+ rsaPrivateKey = (RSAPrivateKey) keyStore.getKey(privateKeyAlias, privateKeyPassword.toCharArray());
+ } else {
+ int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
+ KeyStoreManager tenantKeyStoreManager = KeyStoreManager.getInstance(tenantId);
+ rsaPrivateKey = (RSAPrivateKey) tenantKeyStoreManager.getDefaultPrivateKey();
+ }
+ JWSSigner signer = new RSASSASigner(rsaPrivateKey);
+ SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256), claimsSet);
+ signedJWT.sign(signer);
+ String assertion = signedJWT.serialize();
+ return assertion;
+ } catch (KeyStoreException e) {
+ throw new JWTClientException("Failed loading the keystore.", e);
+ } catch (IOException e) {
+ throw new JWTClientException("Failed parsing the keystore file.", e);
+ } catch (NoSuchAlgorithmException e) {
+ throw new JWTClientException("No such algorithm found RS256.", e);
+ } catch (CertificateException e) {
+ throw new JWTClientException("Failed loading the certificate from the keystore.", e);
+ } catch (UnrecoverableKeyException e) {
+ throw new JWTClientException("Failed loading the keys from the keystore.", e);
+ } catch (JOSEException e) {
+ throw new JWTClientException(e);
+ } catch (Exception e) {
+ //This is thrown when loading default private key.
+ throw new JWTClientException("Failed loading the private key.", e);
+ }
+ }
+
+ private KeyStore loadKeyStore(final File keystoreFile, final String password, final String keyStoreType)
+ throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
+ if (null == keystoreFile) {
+ throw new IllegalArgumentException("Keystore url may not be null");
+ }
+ URI keystoreUri = keystoreFile.toURI();
+ URL keystoreUrl = keystoreUri.toURL();
+ KeyStore keystore = KeyStore.getInstance(keyStoreType);
+ InputStream is = null;
+ try {
+ is = keystoreUrl.openStream();
+ keystore.load(is, null == password ? null : password.toCharArray());
+ } finally {
+ if (null != is) {
+ is.close();
+ }
+ }
+ return keystore;
+ }
+}
+
+
+
diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClientManager.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClientManager.java
new file mode 100644
index 0000000000..cafed79cb9
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClientManager.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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 org.wso2.carbon.device.mgt.jwt.client.extension;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.context.CarbonContext;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.device.mgt.jwt.client.extension.dto.JWTConfig;
+import org.wso2.carbon.device.mgt.jwt.client.extension.exception.JWTClientAlreadyExistsException;
+import org.wso2.carbon.device.mgt.jwt.client.extension.exception.JWTClientConfigurationException;
+import org.wso2.carbon.device.mgt.jwt.client.extension.exception.JWTClientException;
+import org.wso2.carbon.device.mgt.jwt.client.extension.util.JWTClientUtil;
+import org.wso2.carbon.registry.core.Resource;
+import org.wso2.carbon.registry.core.exceptions.RegistryException;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * This creates JWT Client for each tenant.
+ */
+public class JWTClientManager {
+
+ private static Map jwtClientMap;
+ private static JWTClientManager jwtClientCreator;
+ private static final Log log = LogFactory.getLog(JWTClientManager.class);
+ private static final String TENANT_JWT_CONFIG_LOCATION = "/jwt-config/jwt.properties";
+
+ public static JWTClientManager getInstance() {
+ if (jwtClientCreator == null) {
+ synchronized (JWTClientManager.class) {
+ if (jwtClientCreator == null) {
+ jwtClientCreator = new JWTClientManager();
+ }
+ }
+ }
+ return jwtClientCreator;
+ }
+
+ private JWTClientManager() {
+ jwtClientMap = new ConcurrentHashMap<>();
+ }
+
+ /**
+ * this return the jwt based token client to generate token for the tenant.
+ */
+ public JWTClient getJWTClient() throws JWTClientException {
+ String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
+ int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
+ //Get jwt client which has been registered for the tenant.
+ JWTClient jwtClient = getJWTClient(tenantDomain);
+ if (jwtClient == null) {
+ //Create new jwt client for the tenant.
+ try {
+ JWTConfig jwtConfig = new JWTConfig(getJWTConfig(tenantId));
+ jwtClient = new JWTClient(jwtConfig);
+ addJWTClient(tenantDomain, jwtClient);
+ } catch (JWTClientAlreadyExistsException e) {
+ log.warn("Attempting to register a jwt client for the tenant " + tenantDomain +
+ " when one already exists. Returning existing jwt client");
+ return getJWTClient(tenantDomain);
+ } catch (JWTClientConfigurationException e) {
+ throw new JWTClientException("Failed to parse jwt configuration for tenant " + tenantDomain, e);
+ }
+ }
+ return jwtClient;
+ }
+
+ /**
+ * Fetch the jwt client which has been registered under the tenant domain.
+ *
+ * @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.
+ */
+ private JWTClient getJWTClient(String tenantDomain) {
+ if (jwtClientMap.containsKey(tenantDomain)) {
+ return jwtClientMap.get(tenantDomain);
+ }
+ return null;
+ }
+
+ /**
+ * Adds a jwt client to the jwt client map.
+ *
+ * @param tenantDomain - The tenant domain under which the jwt client will be registered.
+ * @param jwtClient - Instance of the jwt client
+ * @throws JWTClientAlreadyExistsException - If a jwt client has already been registered under the tenantdomain
+ */
+ private void addJWTClient(String tenantDomain, JWTClient jwtClient) throws JWTClientAlreadyExistsException {
+ if (jwtClientMap.containsKey(tenantDomain)) {
+ throw new JWTClientAlreadyExistsException("A jwt client has already been created for the tenant " + tenantDomain);
+ }
+ jwtClientMap.put(tenantDomain, jwtClient);
+ }
+
+ /**
+ * Retrieve JWT configs from registry.
+ */
+ private Properties getJWTConfig(int tenantId) throws JWTClientConfigurationException {
+ try {
+ Resource config = JWTClientUtil.getConfigRegistryResourceContent(tenantId, TENANT_JWT_CONFIG_LOCATION);
+ Properties properties = new Properties();
+ if(config != null) {
+ properties.load(config.getContentStream());
+ } else {
+ throw new JWTClientConfigurationException("Failed to load jwt configuration for tenant id : " + tenantId);
+ }
+ return properties;
+ } catch (RegistryException e) {
+ throw new JWTClientConfigurationException("Failed to load the content from registry for tenant " +
+ tenantId, e);
+ } catch (IOException e) {
+ throw new JWTClientConfigurationException(
+ "Failed to parse the content from the registry for tenant " + tenantId, e);
+ }
+ }
+}
diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/constant/JWTConstants.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/constant/JWTConstants.java
new file mode 100644
index 0000000000..41358fe627
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/constant/JWTConstants.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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 org.wso2.carbon.device.mgt.jwt.client.extension.constant;
+
+/**
+ * This holds the constants related JWT client component.
+ */
+public class JWTConstants {
+ public static final String OAUTH_ACCESS_TOKEN = "access_token";
+ public static final String OAUTH_REFRESH_TOKEN = "refresh_token";
+ public static final String OAUTH_EXPIRES_IN = "expires_in";
+ public static final String OAUTH_TOKEN_TYPE = "token_type";
+}
diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/dto/AccessTokenInfo.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/dto/AccessTokenInfo.java
new file mode 100644
index 0000000000..9c12c653ff
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/dto/AccessTokenInfo.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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 org.wso2.carbon.device.mgt.jwt.client.extension.dto;
+
+/**
+ * This holds the token information that return from the token endpoint.
+ */
+public class AccessTokenInfo {
+
+ private String token_type;
+ private long expires_in;
+ private String refresh_token;
+ private String access_token;
+
+ public String getToken_type() {
+ return token_type;
+ }
+
+ public void setToken_type(String token_type) {
+ this.token_type = token_type;
+ }
+
+ public long getExpires_in() {
+ return expires_in;
+ }
+
+ public void setExpires_in(long expres_in) {
+ this.expires_in = expres_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;
+ }
+}
diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/dto/JWTConfig.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/dto/JWTConfig.java
new file mode 100644
index 0000000000..6c41ae8c03
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/dto/JWTConfig.java
@@ -0,0 +1,147 @@
+package org.wso2.carbon.device.mgt.jwt.client.extension.dto;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+public class JWTConfig {
+
+ private static final String JWT_ISSUER = "iss";
+ private static final String JWT_EXPIRATION_TIME = "exp";
+ private static final String JWT_AUDIENCE = "aud";
+ private static final String VALIDITY_PERIOD = "nbf";
+ private static final String JWT_TOKEN_ID = "jti";
+ private static final String JWT_ISSUED_AT = "iat";
+ private static final String SERVER_TIME_SKEW="skew";
+ private static final String JKS_PATH ="KeyStore";
+ private static final String JKS_PRIVATE_KEY_ALIAS ="PrivateKeyAlias";
+ private static final String JKS_PASSWORD ="KeyStorePassword";
+ private static final String JKA_PRIVATE_KEY_PASSWORD = "PrivateKeyPassword";
+ private static final String TOKEN_ENDPOINT = "TokenEndpoint";
+
+ /**
+ * issuer of the JWT
+ */
+ private String issuer;
+
+ /**
+ * skew between IDP and issuer(milliseconds)
+ */
+ private int skew;
+
+ /**
+ * Audience of JWT claim
+ */
+ private List audiences;
+
+ /**
+ * expiration time of JWT (number of minutes from the current time).
+ */
+ private int expirationTime;
+
+ /**
+ * issued Interval from current time of JWT (number of minutes from the current time).
+ */
+ private int issuedInternal;
+
+ /**
+ * nbf time of JWT (number of minutes from current time).
+ */
+ private int validityPeriodInterval;
+
+ /**
+ * JWT Id.
+ */
+ private String jti;
+
+ /**
+ * Token Endpoint;
+ */
+ private String tokenEndpoint;
+
+ /**
+ * Configuration for keystore.
+ */
+ private String keyStorePath;
+ private String keyStorePassword;
+ private String privateKeyAlias;
+ private String privateKeyPassword;
+
+ /**
+ * @param properties load the config from the properties file.
+ */
+ public JWTConfig(Properties properties) {
+ issuer = properties.getProperty(JWT_ISSUER, null);
+ skew = Integer.parseInt(properties.getProperty(SERVER_TIME_SKEW, "0"));
+ issuedInternal = Integer.parseInt(properties.getProperty(JWT_ISSUED_AT,"0"));
+ expirationTime = Integer.parseInt(properties.getProperty(JWT_EXPIRATION_TIME,"15"));
+ validityPeriodInterval = Integer.parseInt(properties.getProperty(VALIDITY_PERIOD,"0"));
+ jti = properties.getProperty(JWT_TOKEN_ID, null);
+ String audience = properties.getProperty(JWT_AUDIENCE, null);
+ if(audience != null) {
+ audiences = getAudience(audience);
+ }
+ //get Keystore params
+ keyStorePath = properties.getProperty(JKS_PATH);
+ keyStorePassword = properties.getProperty(JKS_PASSWORD);
+ privateKeyAlias = properties.getProperty(JKS_PRIVATE_KEY_ALIAS);
+ privateKeyPassword = properties.getProperty(JKA_PRIVATE_KEY_PASSWORD);
+ tokenEndpoint = properties.getProperty(TOKEN_ENDPOINT, "");
+ }
+
+ private static List getAudience(String audience){
+ List audiences = new ArrayList();
+ for(String audi : audience.split(",")){
+ audiences.add(audi.trim());
+ }
+ return audiences;
+ }
+
+ public String getIssuer() {
+ return issuer;
+ }
+
+ public int getSkew() {
+ return skew;
+ }
+
+ public List getAudiences() {
+ return audiences;
+ }
+
+ public int getExpirationTime() {
+ return expirationTime;
+ }
+
+ public int getIssuedInternal() {
+ return issuedInternal;
+ }
+
+ public int getValidityPeriodFromCurrentTime() {
+ return validityPeriodInterval;
+ }
+
+ public String getJti() {
+ return jti;
+ }
+
+ public String getKeyStorePath() {
+ return keyStorePath;
+ }
+
+ public String getKeyStorePassword() {
+ return keyStorePassword;
+ }
+
+ public String getPrivateKeyAlias() {
+ return privateKeyAlias;
+ }
+
+ public String getPrivateKeyPassword() {
+ return privateKeyPassword;
+ }
+
+ public String getTokenEndpoint() {
+ return tokenEndpoint;
+ }
+}
diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/exception/JWTClientAlreadyExistsException.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/exception/JWTClientAlreadyExistsException.java
new file mode 100644
index 0000000000..cdcbfb64b2
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/exception/JWTClientAlreadyExistsException.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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 org.wso2.carbon.device.mgt.jwt.client.extension.exception;
+
+public class JWTClientAlreadyExistsException extends Exception {
+ public JWTClientAlreadyExistsException() {
+ super();
+ }
+
+ public JWTClientAlreadyExistsException(String message) {
+ super(message);
+ }
+
+ public JWTClientAlreadyExistsException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public JWTClientAlreadyExistsException(Throwable cause) {
+ super(cause);
+ }
+
+ protected JWTClientAlreadyExistsException(String message, Throwable cause,
+ boolean enableSuppression,
+ boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/exception/JWTClientConfigurationException.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/exception/JWTClientConfigurationException.java
new file mode 100644
index 0000000000..a7f9d742d4
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/exception/JWTClientConfigurationException.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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 org.wso2.carbon.device.mgt.jwt.client.extension.exception;
+
+public class JWTClientConfigurationException extends Exception {
+ public JWTClientConfigurationException() {
+ super();
+ }
+
+ public JWTClientConfigurationException(String message) {
+ super(message);
+ }
+
+ public JWTClientConfigurationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public JWTClientConfigurationException(Throwable cause) {
+ super(cause);
+ }
+
+ protected JWTClientConfigurationException(String message, Throwable cause,
+ boolean enableSuppression,
+ boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/exception/JWTClientException.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/exception/JWTClientException.java
new file mode 100644
index 0000000000..e434fbcb23
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/exception/JWTClientException.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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 org.wso2.carbon.device.mgt.jwt.client.extension.exception;
+
+public class JWTClientException extends Exception{
+ public JWTClientException() {
+ super();
+ }
+
+ public JWTClientException(String message) {
+ super(message);
+ }
+
+ public JWTClientException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public JWTClientException(Throwable cause) {
+ super(cause);
+ }
+
+ protected JWTClientException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/internal/JWTClientExtensionDataHolder.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/internal/JWTClientExtensionDataHolder.java
new file mode 100644
index 0000000000..39d50961a7
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/internal/JWTClientExtensionDataHolder.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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 org.wso2.carbon.device.mgt.jwt.client.extension.internal;
+
+import org.wso2.carbon.registry.core.service.RegistryService;
+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.tenant.TenantManager;
+
+public class JWTClientExtensionDataHolder {
+ private static JWTClientExtensionDataHolder thisInstance = new JWTClientExtensionDataHolder();
+
+ private TenantRegistryLoader tenantRegistryLoader;
+ private TenantIndexingLoader indexLoader;
+ private RegistryService registryService;
+ private RealmService realmService;
+ private TenantManager tenantManager;
+
+ private JWTClientExtensionDataHolder() {
+ }
+
+
+ public static JWTClientExtensionDataHolder getInstance() {
+ return thisInstance;
+ }
+
+
+ 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;
+ }
+
+ public RegistryService getRegistryService() {
+ return registryService;
+ }
+
+ public void setRegistryService(RegistryService registryService) {
+ this.registryService = registryService;
+ }
+
+ public RealmService getRealmService() {
+ if (realmService == null) {
+ throw new IllegalStateException("Realm service is not initialized properly");
+ }
+ return realmService;
+ }
+
+ public void setRealmService(RealmService realmService) {
+ this.realmService = realmService;
+ this.setTenantManager(realmService);
+ }
+
+ private void setTenantManager(RealmService realmService) {
+ if (realmService == null) {
+ throw new IllegalStateException("Realm service is not initialized properly");
+ }
+ this.tenantManager = realmService.getTenantManager();
+ }
+
+ public TenantManager getTenantManager() {
+ return tenantManager;
+ }
+}
diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/internal/JWTClientExtensionServiceComponent.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/internal/JWTClientExtensionServiceComponent.java
new file mode 100644
index 0000000000..72dd99a56d
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/internal/JWTClientExtensionServiceComponent.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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 org.wso2.carbon.device.mgt.jwt.client.extension.internal;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.osgi.service.component.ComponentContext;
+import org.wso2.carbon.device.mgt.jwt.client.extension.util.JWTClientUtil;
+import org.wso2.carbon.registry.core.exceptions.RegistryException;
+import org.wso2.carbon.registry.core.service.RegistryService;
+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 java.io.IOException;
+
+/**
+ * @scr.component name="org.wso2.carbon.device.mgt.jwt.client.extension.internal.JWTClientExtensionServiceComponent"
+ * immediate="true"
+ * @scr.reference name="registry.service"
+ * interface="org.wso2.carbon.registry.core.service.RegistryService"
+ * cardinality="1..1"
+ * policy="dynamic"
+ * bind="setRegistryService"
+ * unbind="unsetRegistryService"
+ * @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"
+ * interface="org.wso2.carbon.user.core.service.RealmService"
+ * cardinality="1..1"
+ * policy="dynamic"
+ * bind="setRealmService"
+ * unbind="unsetRealmService"
+ */
+public class JWTClientExtensionServiceComponent {
+
+ private static Log log = LogFactory.getLog(JWTClientExtensionServiceComponent.class);
+
+ protected void activate(ComponentContext componentContext) {
+ if (log.isDebugEnabled()) {
+ log.debug("Initializing jwt extension bundle");
+ }
+ try {
+ JWTClientUtil.initialize();
+ } catch (RegistryException e) {
+ log.error("Failed loading the jwt config from registry.", e);
+ } catch (IOException e) {
+ log.error("Failed loading the jwt config from the file system.", e);
+ }
+ }
+
+ protected void deactivate(ComponentContext componentContext) {
+ //do nothing
+ }
+
+ protected void setRegistryService(RegistryService registryService) {
+ if (registryService != null && log.isDebugEnabled()) {
+ log.debug("Registry service initialized");
+ }
+ JWTClientExtensionDataHolder.getInstance().setRegistryService(registryService);
+ }
+
+ protected void unsetRegistryService(RegistryService registryService) {
+ JWTClientExtensionDataHolder.getInstance().setRegistryService(null);
+ }
+
+ protected void setTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) {
+ JWTClientExtensionDataHolder.getInstance().setTenantRegistryLoader(tenantRegistryLoader);
+ }
+
+ protected void unsetTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) {
+ JWTClientExtensionDataHolder.getInstance().setTenantRegistryLoader(null);
+ }
+
+ protected void setIndexLoader(TenantIndexingLoader indexLoader) {
+ if (indexLoader != null && log.isDebugEnabled()) {
+ log.debug("IndexLoader service initialized");
+ }
+ JWTClientExtensionDataHolder.getInstance().setIndexLoaderService(indexLoader);
+ }
+
+ protected void unsetIndexLoader(TenantIndexingLoader indexLoader) {
+ JWTClientExtensionDataHolder.getInstance().setIndexLoaderService(null);
+ }
+
+ /**
+ * Sets Realm Service.
+ *
+ * @param realmService An instance of RealmService
+ */
+ protected void setRealmService(RealmService realmService) {
+ if (log.isDebugEnabled()) {
+ log.debug("Setting Realm Service");
+ }
+ JWTClientExtensionDataHolder.getInstance().setRealmService(realmService);
+ }
+
+ /**
+ * Unsets Realm Service.
+ *
+ * @param realmService An instance of RealmService
+ */
+ protected void unsetRealmService(RealmService realmService) {
+ if (log.isDebugEnabled()) {
+ log.debug("Unsetting Realm Service");
+ }
+ JWTClientExtensionDataHolder.getInstance().setRealmService(null);
+ }
+}
diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/util/JWTClientUtil.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/util/JWTClientUtil.java
new file mode 100644
index 0000000000..087fd17294
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/util/JWTClientUtil.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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 org.wso2.carbon.device.mgt.jwt.client.extension.util;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLContextBuilder;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.wso2.carbon.base.MultitenantConstants;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.device.mgt.jwt.client.extension.internal.JWTClientExtensionDataHolder;
+import org.wso2.carbon.registry.core.Registry;
+import org.wso2.carbon.registry.core.Resource;
+import org.wso2.carbon.registry.core.exceptions.RegistryException;
+import org.wso2.carbon.registry.core.service.RegistryService;
+import org.wso2.carbon.registry.core.service.TenantRegistryLoader;
+import org.wso2.carbon.utils.CarbonUtils;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * This is the utility class that is used for JWT Client.
+ */
+public class JWTClientUtil {
+
+ private static final Log log = LogFactory.getLog(JWTClientUtil.class);
+ private static final String HTTPS_PROTOCOL = "https";
+ private static final String TENANT_JWT_CONFIG_LOCATION = "/jwt-config/jwt.properties";
+ private static final String JWT_CONFIG_FILE_NAME = "jwt.properties";
+ private static final String SUPERTENANT_JWT_CONFIG_LOCATION =
+ CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + JWT_CONFIG_FILE_NAME;
+ /**
+ * Return a http client instance
+ * @param protocol- service endpoint protocol http/https
+ * @return
+ */
+ public static HttpClient getHttpClient(String protocol)
+ throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
+ HttpClient httpclient;
+ if (HTTPS_PROTOCOL.equals(protocol)) {
+ SSLContextBuilder builder = new SSLContextBuilder();
+ builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
+ SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
+ httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
+ } else {
+ httpclient = HttpClients.createDefault();
+ }
+ return httpclient;
+ }
+
+ public static String getResponseString(HttpResponse httpResponse) throws IOException {
+ BufferedReader br = null;
+ try {
+ br = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
+ String readLine;
+ String response = "";
+ while (((readLine = br.readLine()) != null)) {
+ response += readLine;
+ }
+ return response;
+ } finally {
+ EntityUtils.consumeQuietly(httpResponse.getEntity());
+ if (br != null) {
+ try {
+ br.close();
+ } catch (IOException e) {
+ log.warn("Error while closing the connection! " + e.getMessage());
+ }
+ }
+ }
+ }
+
+ public static void initialize() throws RegistryException, IOException {
+ Resource resource = getConfigRegistryResourceContent(MultitenantConstants.SUPER_TENANT_ID, TENANT_JWT_CONFIG_LOCATION);
+ if (resource == null) {
+ File configFile = new File(SUPERTENANT_JWT_CONFIG_LOCATION);
+ String contents = FileUtils.readFileToString(configFile, "UTF-8");
+ addJWTConfigResourceToRegistry(MultitenantConstants.SUPER_TENANT_ID, contents);
+ }
+ }
+
+ /**
+ * Get the jwt details from the registry for tenants.
+ *
+ * @param tenantId for identify tenant space.
+ * @param registryLocation retrive the config file from tenant space.
+ * @return the config for tenant
+ * @throws RegistryException
+ */
+ public static Resource getConfigRegistryResourceContent(int tenantId, final String registryLocation)
+ throws RegistryException {
+ try {
+ Resource resource = null;
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
+ RegistryService registryService = JWTClientExtensionDataHolder.getInstance().getRegistryService();
+ if (registryService != null) {
+ Registry registry = registryService.getConfigSystemRegistry(tenantId);
+ JWTClientUtil.loadTenantRegistry(tenantId);
+ if (registry.resourceExists(registryLocation)) {
+ resource = registry.get(registryLocation);
+ }
+ }
+ return resource;
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+
+ /**
+ * Get the jwt details from the registry for tenants.
+ *
+ * @param tenantId for accesing tenant space.
+ * @return the config for tenant
+ * @throws RegistryException
+ */
+ public static void addJWTConfigResourceToRegistry(int tenantId, String content)
+ throws RegistryException {
+ try {
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
+ RegistryService registryService = JWTClientExtensionDataHolder.getInstance().getRegistryService();
+ if (registryService != null) {
+ Registry registry = registryService.getConfigSystemRegistry(tenantId);
+ JWTClientUtil.loadTenantRegistry(tenantId);
+ if (!registry.resourceExists(TENANT_JWT_CONFIG_LOCATION)) {
+ Resource resource = registry.newResource();
+ resource.setContent(content.getBytes());
+ registry.put(TENANT_JWT_CONFIG_LOCATION, resource);
+ }
+ }
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+
+ private static void loadTenantRegistry(int tenantId) throws RegistryException {
+ TenantRegistryLoader tenantRegistryLoader = JWTClientExtensionDataHolder.getInstance().getTenantRegistryLoader();
+ JWTClientExtensionDataHolder.getInstance().getIndexLoaderService().loadTenantIndex(tenantId);
+ tenantRegistryLoader.loadTenantRegistry(tenantId);
+ }
+}
diff --git a/components/identity-extensions/pom.xml b/components/identity-extensions/pom.xml
index e63415d853..b55a9102fe 100644
--- a/components/identity-extensions/pom.xml
+++ b/components/identity-extensions/pom.xml
@@ -29,13 +29,13 @@
4.0.0
org.wso2.carbon.devicemgt
identity-extensions
- 1.1.0-SNAPSHOT
pom
WSO2 Carbon - Dynamic Client Registration Component
http://wso2.org
org.wso2.carbon.device.mgt.oauth.extensions
+ org.wso2.carbon.identity.jwt.client.extension
dynamic-client-registration
backend-oauth-authenticator
diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml
index c72eae9bf5..08114db190 100644
--- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml
+++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml
@@ -199,7 +199,7 @@
org.wso2.carbon.device.mgt.common
- org.apache.httpcomponents.wso2
+ org.wso2.orbit.org.apache.httpcomponents
httpclient