You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stratos.apache.org by ud...@apache.org on 2014/12/05 17:23:23 UTC

[4/6] stratos git commit: oAuth feature for metadata service

oAuth feature for metadata service


Project: http://git-wip-us.apache.org/repos/asf/stratos/repo
Commit: http://git-wip-us.apache.org/repos/asf/stratos/commit/c0651601
Tree: http://git-wip-us.apache.org/repos/asf/stratos/tree/c0651601
Diff: http://git-wip-us.apache.org/repos/asf/stratos/diff/c0651601

Branch: refs/heads/master
Commit: c0651601036d11f619e6ef7d2de27407fd381a73
Parents: b766e12
Author: Udara Liyanage <ud...@wso2.com>
Authored: Wed Dec 3 22:36:53 2014 +0530
Committer: Udara Liyanage <ud...@wso2.com>
Committed: Fri Dec 5 19:31:33 2014 +0530

----------------------------------------------------------------------
 .../org.apache.stratos.custom.handlers/pom.xml  | 105 ++++++++
 .../authentication/SignedJWTAuthenticator.java  | 225 +++++++++++++++++
 .../ClientCredentialsGrantHandler.java          | 242 +++++++++++++++++++
 .../SignedJWTAuthenticatorServiceComponent.java |  97 ++++++++
 components/org.apache.stratos.manager/pom.xml   |  15 ++
 ...ntityApplicationManagementServiceClient.java | 202 ++++++++++++++++
 .../apache/stratos/manager/client/Utility.java  |  86 +++++++
 .../manager/client/oAuthAdminServiceClient.java |  96 ++++++++
 .../manager/utils/CartridgeConstants.java       |   1 +
 .../metadataservice/handlers/OAuthHandler.java  | 147 ++++++-----
 .../WEB-INF/cxf-servlet.xml                     |   3 +-
 .../rest/endpoint/api/StratosApiV41Utils.java   |  22 ++
 components/pom.xml                              |   2 +
 .../pom.xml                                     |  15 +-
 features/common/pom.xml                         |   3 +-
 products/stratos/modules/p2-profile-gen/pom.xml |   9 +
 16 files changed, 1206 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/components/org.apache.stratos.custom.handlers/pom.xml
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.custom.handlers/pom.xml b/components/org.apache.stratos.custom.handlers/pom.xml
new file mode 100644
index 0000000..24a9454
--- /dev/null
+++ b/components/org.apache.stratos.custom.handlers/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.stratos</groupId>
+        <artifactId>stratos-components-parent</artifactId>
+        <version>4.1.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>org.apache.stratos.custom.handlers</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Stratos - Custome Handlers</name>
+    <description>Custome Handlers</description>
+    <url>http://apache.org</url>
+    <dependencies>
+        <dependency>
+            <groupId>org.wso2.carbon</groupId>
+            <artifactId>org.wso2.carbon.identity.oauth</artifactId>
+            <version>4.2.3</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.nimbusds</groupId>
+            <artifactId>nimbus-jose-jwt</artifactId>
+            <version>2.26.1</version>
+        </dependency>
+        <dependency>
+            <groupId>net.minidev</groupId>
+            <artifactId>json-smart</artifactId>
+            <version>1.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.wso2.carbon</groupId>
+            <artifactId>org.wso2.carbon.logging</artifactId>
+            <version>4.2.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.wso2.carbon</groupId>
+            <artifactId>org.wso2.carbon.core</artifactId>
+            <version>4.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.wso2.carbon</groupId>
+            <artifactId>org.wso2.carbon.core.common</artifactId>
+            <version>4.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.wso2.carbon</groupId>
+            <artifactId>org.wso2.carbon.core.services</artifactId>
+            <version>4.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.wso2.carbon</groupId>
+            <artifactId>org.wso2.carbon.utils</artifactId>
+            <version>4.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>opensaml.wso2</groupId>
+            <artifactId>opensaml2</artifactId>
+            <version>2.4.1.wso2v1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.nimbusds.wso2</groupId>
+            <artifactId>nimbus-jose-jwt</artifactId>
+            <version>2.26.1.wso2v2</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>1.4.0</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>
+                            ${project.artifactId}
+                        </Bundle-SymbolicName>
+                        <Bundle-Name>${project.artifactId}</Bundle-Name>
+                        <Import-Package>
+                            org.wso2.carbon.identity.oauth2.*; version="4.2.3",
+                            *;resolution:=optional,
+                        </Import-Package>
+                        <Export-Package>
+                            !org.wso2.carbon.identity.authenticator.signedjwt.internal,
+                            org.apache.stratos.custom.handlers.*,
+                        </Export-Package>
+                        <Embed-Dependency>
+                            nimbus-jose-jwt|json-smart;scope=compile|runtime;inline=false
+                        </Embed-Dependency>
+                        <!--<DynamicImport-Package>*</DynamicImport-Package>-->
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/components/org.apache.stratos.custom.handlers/src/main/java/org/apache/stratos/custom/handlers/authentication/SignedJWTAuthenticator.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.custom.handlers/src/main/java/org/apache/stratos/custom/handlers/authentication/SignedJWTAuthenticator.java b/components/org.apache.stratos.custom.handlers/src/main/java/org/apache/stratos/custom/handlers/authentication/SignedJWTAuthenticator.java
new file mode 100644
index 0000000..b98c3aa
--- /dev/null
+++ b/components/org.apache.stratos.custom.handlers/src/main/java/org/apache/stratos/custom/handlers/authentication/SignedJWTAuthenticator.java
@@ -0,0 +1,225 @@
+/*
+ *  Copyright (c) WSO2 Inc. (http://wso2.com) 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.apache.stratos.custom.handlers.authentication;
+
+import com.nimbusds.jose.JWSVerifier;
+import com.nimbusds.jose.crypto.RSASSAVerifier;
+import com.nimbusds.jwt.SignedJWT;
+import org.apache.axiom.util.base64.Base64Utils;
+import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.transport.http.HTTPConstants;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.custom.handlers.internal.SignedJWTAuthenticatorServiceComponent;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
+import org.wso2.carbon.base.MultitenantConstants;
+import org.wso2.carbon.core.security.AuthenticatorsConfiguration;
+import org.wso2.carbon.core.services.authentication.CarbonServerAuthenticator;
+import org.wso2.carbon.core.services.util.CarbonAuthenticationUtil;
+import org.wso2.carbon.core.util.KeyStoreManager;
+import org.wso2.carbon.user.api.TenantManager;
+import org.wso2.carbon.user.api.UserStoreManager;
+import org.wso2.carbon.utils.AuthenticationObserver;
+import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * SignedJWTAuthenticator Authenticate a user by a JWT token. JWT token should contains
+ * a username as a claim and that user should be a valid user.
+ */
+public class SignedJWTAuthenticator implements CarbonServerAuthenticator {
+
+    private static final int DEFAULT_PRIORITY_LEVEL = 20;
+    private static final String AUTHENTICATOR_NAME = "SignedJWTAuthenticator";
+    private static final String AUTHORIZATION_HEADER_TYPE = "Bearer";
+    private static final String SIGNED_JWT_AUTH_USERNAME = "Username";
+
+    private static final Log log = LogFactory.getLog(SignedJWTAuthenticator.class);
+
+    @Override
+    public int getPriority() {
+        AuthenticatorsConfiguration authenticatorsConfiguration =
+                AuthenticatorsConfiguration.getInstance();
+        AuthenticatorsConfiguration.AuthenticatorConfig authenticatorConfig =
+                authenticatorsConfiguration.getAuthenticatorConfig(AUTHENTICATOR_NAME);
+        if (authenticatorConfig != null && authenticatorConfig.getPriority() > 0) {
+            return authenticatorConfig.getPriority();
+        }
+        return DEFAULT_PRIORITY_LEVEL;
+    }
+
+    @Override
+    public boolean isDisabled() {
+        AuthenticatorsConfiguration authenticatorsConfiguration =
+                AuthenticatorsConfiguration.getInstance();
+        AuthenticatorsConfiguration.AuthenticatorConfig authenticatorConfig =
+                authenticatorsConfiguration.getAuthenticatorConfig(AUTHENTICATOR_NAME);
+        return authenticatorConfig != null && authenticatorConfig.isDisabled();
+    }
+
+    @Override
+    public boolean authenticateWithRememberMe(MessageContext msgCxt) {
+        return false;
+    }
+
+    @Override
+    public String getAuthenticatorName() {
+        return AUTHENTICATOR_NAME;
+    }
+
+    @Override
+    public boolean isAuthenticated(MessageContext msgCxt) {
+        boolean isAuthenticated = false;
+        HttpServletRequest request =
+                (HttpServletRequest) msgCxt.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
+        try {
+            //Get the filesystem keystore default primary certificate
+            KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(
+                    MultitenantConstants.SUPER_TENANT_ID);
+            keyStoreManager.getDefaultPrimaryCertificate();
+
+            String authorizationHeader = request.getHeader(HTTPConstants.HEADER_AUTHORIZATION);
+            String headerData = decodeAuthorizationHeader(authorizationHeader);
+
+            JWSVerifier verifier =
+                    new RSASSAVerifier((RSAPublicKey) keyStoreManager.getDefaultPublicKey());
+            SignedJWT jwsObject = SignedJWT.parse(headerData);
+
+            if (jwsObject.verify(verifier)) {
+                String userName = jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_USERNAME);
+                String tenantDomain = MultitenantUtils.getTenantDomain(userName);
+                userName = MultitenantUtils.getTenantAwareUsername(userName);
+                TenantManager tenantManager = SignedJWTAuthenticatorServiceComponent
+                        .getRealmService().getTenantManager();
+                int tenantId = tenantManager.getTenantId(tenantDomain);
+
+                handleAuthenticationStarted(tenantId);
+
+                UserStoreManager userStore = SignedJWTAuthenticatorServiceComponent
+                        .getRealmService().getTenantUserRealm(tenantId).getUserStoreManager();
+                if (userStore.isExistingUser(userName)) {
+                    isAuthenticated = true;
+                }
+
+                if (isAuthenticated) {
+                    CarbonAuthenticationUtil.onSuccessAdminLogin(request.getSession(), userName,
+                            tenantId, tenantDomain,
+                            "Signed JWT Authentication");
+                    handleAuthenticationCompleted(tenantId, true);
+                    return true;
+                } else {
+                    log.error(
+                            "Authentication Request is rejected. User does not exists in UserStore");
+                    CarbonAuthenticationUtil
+                            .onFailedAdminLogin(request.getSession(), userName, tenantId,
+                                    "Signed JWT Authentication",
+                                    "User does not exists in UserStore");
+                    handleAuthenticationCompleted(tenantId, false);
+                    return false;
+                }
+            }
+        } catch (Exception e) {
+            log.error("Error authenticating the user " + e.getMessage(), e);
+        }
+        return isAuthenticated;
+    }
+
+    @Override
+    public boolean isHandle(MessageContext msgCxt) {
+        HttpServletRequest request =
+                (HttpServletRequest) msgCxt.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
+        String authorizationHeader = request.getHeader(HTTPConstants.HEADER_AUTHORIZATION);
+        if (authorizationHeader != null) {
+            String authType = getAuthType(authorizationHeader);
+            if (authType != null && authType.equalsIgnoreCase(AUTHORIZATION_HEADER_TYPE)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Gets the authentication type in authorization header.
+     *
+     * @param authorizationHeader The authorization header - Authorization: Bearer QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
+     * @return The authentication type mentioned in authorization header.
+     */
+    private String getAuthType(String authorizationHeader) {
+        String[] splitValues = null;
+        if (authorizationHeader != null) {
+            splitValues = authorizationHeader.trim().split(" ");
+        }
+        if (splitValues == null || splitValues.length == 0) {
+            return null;
+        }
+        return splitValues[0].trim();
+    }
+
+    private String decodeAuthorizationHeader(String authorizationHeader) {
+        String[] splitValues = authorizationHeader.trim().split(" ");
+        byte[] decodedBytes = Base64Utils.decode(splitValues[1].trim());
+        if (decodedBytes != null) {
+            return new String(decodedBytes);
+        } else {
+            log.debug(
+                    "Error decoding authorization header. Could not retrieve user name and password.");
+            return null;
+        }
+    }
+
+    private void handleAuthenticationStarted(int tenantId) {
+        BundleContext bundleContext = SignedJWTAuthenticatorServiceComponent.getBundleContext();
+        if (bundleContext != null) {
+            ServiceTracker tracker =
+                    new ServiceTracker(bundleContext,
+                            AuthenticationObserver.class.getName(), null);
+            tracker.open();
+            Object[] services = tracker.getServices();
+            if (services != null) {
+                for (Object service : services) {
+                    ((AuthenticationObserver) service).startedAuthentication(tenantId);
+                }
+            }
+            tracker.close();
+        }
+    }
+
+    private void handleAuthenticationCompleted(int tenantId, boolean isSuccessful) {
+        BundleContext bundleContext = SignedJWTAuthenticatorServiceComponent.getBundleContext();
+        if (bundleContext != null) {
+            ServiceTracker tracker =
+                    new ServiceTracker(bundleContext,
+                            AuthenticationObserver.class.getName(), null);
+            tracker.open();
+            Object[] services = tracker.getServices();
+            if (services != null) {
+                for (Object service : services) {
+                    ((AuthenticationObserver) service).completedAuthentication(
+                            tenantId, isSuccessful);
+                }
+            }
+            tracker.close();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/components/org.apache.stratos.custom.handlers/src/main/java/org/apache/stratos/custom/handlers/granttype/ClientCredentialsGrantHandler.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.custom.handlers/src/main/java/org/apache/stratos/custom/handlers/granttype/ClientCredentialsGrantHandler.java b/components/org.apache.stratos.custom.handlers/src/main/java/org/apache/stratos/custom/handlers/granttype/ClientCredentialsGrantHandler.java
new file mode 100644
index 0000000..843186c
--- /dev/null
+++ b/components/org.apache.stratos.custom.handlers/src/main/java/org/apache/stratos/custom/handlers/granttype/ClientCredentialsGrantHandler.java
@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.stratos.custom.handlers.granttype;
+
+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.PlainJWT;
+import com.nimbusds.jwt.SignedJWT;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.oltu.openidconnect.as.messages.IDTokenBuilder;
+import org.apache.oltu.openidconnect.as.messages.IDTokenException;
+import org.wso2.carbon.base.MultitenantConstants;
+import org.wso2.carbon.core.util.KeyStoreManager;
+import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenRespDTO;
+import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
+import org.wso2.carbon.identity.oauth2.token.handlers.grant.AbstractAuthorizationGrantHandler;
+
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.Certificate;
+import java.security.interfaces.RSAPrivateKey;
+import java.text.ParseException;
+import java.util.Calendar;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Grant Handler for Grant Type : client_credentials
+ */
+public class ClientCredentialsGrantHandler extends AbstractAuthorizationGrantHandler {
+
+    private static Log log = LogFactory.getLog(ClientCredentialsGrantHandler.class);
+    private static ConcurrentHashMap<Integer, Key> privateKeys =
+            new ConcurrentHashMap<Integer, Key>();
+    private static ConcurrentHashMap<Integer, Certificate> publicCerts =
+            new ConcurrentHashMap<Integer, Certificate>();
+
+    @Override
+    public boolean validateGrant(OAuthTokenReqMessageContext tokReqMsgCtx)
+            throws IdentityOAuth2Exception {
+        // By this time, we have already validated client credentials.
+        tokReqMsgCtx.setScope(tokReqMsgCtx.getOauth2AccessTokenReqDTO().getScope());
+        return true;
+    }
+
+    public boolean issueRefreshToken() throws IdentityOAuth2Exception {
+        return false;
+    }
+
+    public boolean isOfTypeApplicationUser() throws IdentityOAuth2Exception {
+        return false;
+    }
+
+    public OAuth2AccessTokenRespDTO issue(OAuthTokenReqMessageContext tokReqMsgCtx) throws IdentityOAuth2Exception {
+
+        OAuthServerConfiguration config = OAuthServerConfiguration.getInstance();
+        String issuer = config.getOpenIDConnectIDTokenIssuerIdentifier();
+        String subject = tokReqMsgCtx.getAuthorizedUser();
+        String audience = tokReqMsgCtx.getOauth2AccessTokenReqDTO().getClientId();
+        String authorizedParty = tokReqMsgCtx.getOauth2AccessTokenReqDTO().getClientId();
+
+        OAuth2AccessTokenRespDTO tokenRespDTO = getTokenDTO(tokReqMsgCtx);
+        int lifetime = Integer.parseInt(config.getOpenIDConnectIDTokenExpiration()) * 1000;
+        int curTime = (int) Calendar.getInstance().getTimeInMillis();
+
+        String applicationId = tokReqMsgCtx.getScope()[0];
+
+        IDTokenBuilder builder =
+                new IDTokenBuilder().setIssuer(issuer)
+                        .setSubject(subject)
+                        .setAudience(audience)
+                        .setAuthorizedParty(authorizedParty)
+                        .setExpiration(curTime + lifetime)
+                        .setIssuedAt((int) Calendar.getInstance().getTimeInMillis())
+                        .setClaim("appId", applicationId);
+
+        String plainIDToken;
+        try {
+            plainIDToken = builder.buildIDToken();
+        } catch (IDTokenException e) {
+            String message = "Error while building ID token";
+            throw new RuntimeException(message, e);
+        }
+
+        String signedJwtKey;
+        try {
+            PlainJWT plainJWT = PlainJWT.parse(plainIDToken);
+            plainIDToken = plainJWT.serialize();
+            signedJwtKey = signJWT(plainIDToken, tokReqMsgCtx);
+        } catch (ParseException e) {
+            String message = "Error while passing ID token";
+            throw new RuntimeException(message, e);
+        }
+
+        tokenRespDTO.setIDToken(signedJwtKey);
+        return tokenRespDTO;
+    }
+
+    private OAuth2AccessTokenRespDTO getTokenDTO(OAuthTokenReqMessageContext tokReqMsgCtx) throws IdentityOAuth2Exception {
+        return super.issue(tokReqMsgCtx);
+    }
+
+    protected String signJWT(String payLoad, OAuthTokenReqMessageContext request)
+            throws IdentityOAuth2Exception {
+        JWSAlgorithm jwsAlgorithm =
+                mapSignatureAlgorithm(OAuthServerConfiguration.getInstance()
+                        .getSignatureAlgorithm());
+        if (JWSAlgorithm.RS256.equals(jwsAlgorithm) || JWSAlgorithm.RS384.equals(jwsAlgorithm) ||
+                JWSAlgorithm.RS512.equals(jwsAlgorithm)) {
+            return signJWTWithRSA(payLoad, jwsAlgorithm, request);
+        }
+        log.error("UnSupported Signature Algorithm");
+        throw new IdentityOAuth2Exception("UnSupported Signature Algorithm");
+    }
+
+    protected String signJWTWithRSA(String payLoad, JWSAlgorithm jwsAlgorithm,
+                                    OAuthTokenReqMessageContext request)
+            throws IdentityOAuth2Exception {
+        try {
+            String tenantDomain = request.getOauth2AccessTokenReqDTO().getTenantDomain();
+            int tenantId = request.getTenantID();
+            if (tenantDomain == null) {
+                tenantDomain = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
+            }
+            if (tenantId == 0) {
+                tenantId = MultitenantConstants.SUPER_TENANT_ID;
+            }
+            Key privateKey = null;
+
+            if (!(privateKeys.containsKey(tenantId))) {
+                // get tenant's key store manager
+                KeyStoreManager tenantKSM = KeyStoreManager.getInstance(tenantId);
+
+                if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
+                    // derive key store name
+                    String ksName = tenantDomain.trim().replace(".", "-");
+                    String jksName = ksName + ".jks";
+                    // obtain private key
+                    privateKey = tenantKSM.getPrivateKey(jksName, tenantDomain);
+
+                } else {
+                    try {
+                        privateKey = tenantKSM.getDefaultPrivateKey();
+                    } catch (Exception e) {
+                        log.error("Error while obtaining private key for super tenant", e);
+                    }
+                }
+                if (privateKey != null) {
+                    privateKeys.put(tenantId, privateKey);
+                }
+            } else {
+                privateKey = privateKeys.get(tenantId);
+            }
+
+            Certificate publicCert;
+
+            if (!(publicCerts.containsKey(tenantId))) {
+                // get tenant's key store manager
+                KeyStoreManager tenantKSM = KeyStoreManager.getInstance(tenantId);
+
+                KeyStore keyStore;
+                if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
+                    // derive key store name
+                    String ksName = tenantDomain.trim().replace(".", "-");
+                    String jksName = ksName + ".jks";
+                    keyStore = tenantKSM.getKeyStore(jksName);
+                    publicCert = keyStore.getCertificate(tenantDomain);
+                } else {
+                    publicCert = tenantKSM.getDefaultPrimaryCertificate();
+                }
+                if (publicCert != null) {
+                    publicCerts.put(tenantId, publicCert);
+                }
+            } else {
+                publicCert = publicCerts.get(tenantId);
+            }
+
+            JWSSigner signer = new RSASSASigner((RSAPrivateKey) privateKey);
+            SignedJWT signedJWT =
+                    new SignedJWT(new JWSHeader(jwsAlgorithm),
+                            PlainJWT.parse(payLoad).getJWTClaimsSet());
+            signedJWT.sign(signer);
+            return signedJWT.serialize();
+        } catch (KeyStoreException e) {
+            log.error("Error in obtaining tenant's keystore", e);
+            throw new IdentityOAuth2Exception("Error in obtaining tenant's keystore", e);
+        } catch (JOSEException e) {
+            log.error("Error in obtaining tenant's keystore", e);
+            throw new IdentityOAuth2Exception("Error in obtaining tenant's keystore", e);
+        } catch (Exception e) {
+            log.error("Error in obtaining tenant's keystore", e);
+            throw new IdentityOAuth2Exception("Error in obtaining tenant's keystore", e);
+        }
+    }
+
+    protected JWSAlgorithm mapSignatureAlgorithm(String signatureAlgorithm)
+            throws IdentityOAuth2Exception {
+        if ("SHA256withRSA".equals(signatureAlgorithm)) {
+            return JWSAlgorithm.RS256;
+        } else if ("SHA384withRSA".equals(signatureAlgorithm)) {
+            return JWSAlgorithm.RS384;
+        } else if ("SHA512withRSA".equals(signatureAlgorithm)) {
+            return JWSAlgorithm.RS512;
+        } else if ("SHA256withHMAC".equals(signatureAlgorithm)) {
+            return JWSAlgorithm.HS256;
+        } else if ("SHA384withHMAC".equals(signatureAlgorithm)) {
+            return JWSAlgorithm.HS384;
+        } else if ("SHA512withHMAC".equals(signatureAlgorithm)) {
+            return JWSAlgorithm.HS512;
+        } else if ("SHA256withEC".equals(signatureAlgorithm)) {
+            return JWSAlgorithm.ES256;
+        } else if ("SHA384withEC".equals(signatureAlgorithm)) {
+            return JWSAlgorithm.ES384;
+        } else if ("SHA512withEC".equals(signatureAlgorithm)) {
+            return JWSAlgorithm.ES512;
+        }
+        log.error("Unsupported Signature Algorithm in identity.xml");
+        throw new IdentityOAuth2Exception("Unsupported Signature Algorithm in identity.xml");
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/components/org.apache.stratos.custom.handlers/src/main/java/org/apache/stratos/custom/handlers/internal/SignedJWTAuthenticatorServiceComponent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.custom.handlers/src/main/java/org/apache/stratos/custom/handlers/internal/SignedJWTAuthenticatorServiceComponent.java b/components/org.apache.stratos.custom.handlers/src/main/java/org/apache/stratos/custom/handlers/internal/SignedJWTAuthenticatorServiceComponent.java
new file mode 100644
index 0000000..390368b
--- /dev/null
+++ b/components/org.apache.stratos.custom.handlers/src/main/java/org/apache/stratos/custom/handlers/internal/SignedJWTAuthenticatorServiceComponent.java
@@ -0,0 +1,97 @@
+/*
+ *  Copyright (c) WSO2 Inc. (http://wso2.com) 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.apache.stratos.custom.handlers.internal;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.custom.handlers.authentication.SignedJWTAuthenticator;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+import org.wso2.carbon.CarbonConstants;
+import org.wso2.carbon.core.services.authentication.CarbonServerAuthenticator;
+import org.wso2.carbon.user.core.service.RealmService;
+
+import java.util.Hashtable;
+
+
+/**
+ * @scr.component name=
+ * "signedjwt.SignedJWTAuthenticatorServiceComponent"
+ * immediate="true"
+ * @scr.reference name="user.realmservice.default"
+ * interface="org.wso2.carbon.user.core.service.RealmService"
+ * cardinality="1..1" policy="dynamic"
+ * bind="setRealmService"
+ * unbind="unsetRealmService"
+ */
+public class SignedJWTAuthenticatorServiceComponent {
+
+    private static final Log log = LogFactory.getLog(SignedJWTAuthenticatorServiceComponent.class);
+    private static RealmService realmService = null;
+    private static BundleContext bundleContext = null;
+
+    public static RealmService getRealmService() {
+        return realmService;
+    }
+
+    protected void setRealmService(RealmService realmService) {
+        if (log.isDebugEnabled()) {
+            log.debug("RealmService acquired");
+        }
+        SignedJWTAuthenticatorServiceComponent.realmService = realmService;
+    }
+
+    public static BundleContext getBundleContext() {
+        return bundleContext;
+    }
+
+    public static void setBundleContext(BundleContext bundleContext) {
+        SignedJWTAuthenticatorServiceComponent.bundleContext = bundleContext;
+    }
+
+    protected void activate(ComponentContext cxt) {
+        try {
+            SignedJWTAuthenticator authenticator = new SignedJWTAuthenticator();
+            SignedJWTAuthenticatorServiceComponent.setBundleContext(cxt.getBundleContext());
+            Hashtable<String, String> props = new Hashtable<String, String>();
+            props.put(CarbonConstants.AUTHENTICATOR_TYPE, authenticator.getAuthenticatorName());
+            cxt.getBundleContext().registerService(CarbonServerAuthenticator.class.getName(),
+                    authenticator, props);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            // throwing so that server will not start
+            throw new RuntimeException("Failed to start the Signed JWT Authenticator Bundle" +
+                    e.getMessage(), e);
+        }
+        log.debug("Signed JWT Authenticator is activated");
+    }
+
+    protected void deactivate(ComponentContext context) {
+        if (log.isDebugEnabled()) {
+            log.debug("Signed JWT Authenticator is deactivated");
+        }
+    }
+
+    protected void unsetRealmService(RealmService realmService) {
+        SignedJWTAuthenticatorServiceComponent.realmService = null;
+    }
+
+}
+

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/components/org.apache.stratos.manager/pom.xml
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/pom.xml b/components/org.apache.stratos.manager/pom.xml
index 9e1386f..1f3d82a 100644
--- a/components/org.apache.stratos.manager/pom.xml
+++ b/components/org.apache.stratos.manager/pom.xml
@@ -126,6 +126,21 @@
 		        <artifactId>mqtt-client</artifactId>
 		        <version>0.4.0</version>
    		 </dependency>
+		<dependency>
+			<groupId>org.wso2.carbon</groupId>
+			<artifactId>org.wso2.carbon.identity.oauth</artifactId>
+			<version>4.2.3</version>
+		</dependency>
+		<dependency>
+			<groupId>org.wso2.carbon</groupId>
+			<artifactId>org.wso2.carbon.identity.oauth.stub</artifactId>
+			<version>4.2.3</version>
+		</dependency>
+		<dependency>
+			<groupId>org.wso2.carbon</groupId>
+			<artifactId>org.wso2.carbon.identity.application.mgt.stub</artifactId>
+			<version>4.2.0</version>
+		</dependency>
     </dependencies>
 
 	<build>

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/client/IdentityApplicationManagementServiceClient.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/client/IdentityApplicationManagementServiceClient.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/client/IdentityApplicationManagementServiceClient.java
new file mode 100644
index 0000000..7dccc7c
--- /dev/null
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/client/IdentityApplicationManagementServiceClient.java
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.stratos.manager.client;
+
+import org.apache.amber.oauth2.client.OAuthClient;
+import org.apache.amber.oauth2.client.URLConnectionClient;
+import org.apache.amber.oauth2.client.request.OAuthClientRequest;
+import org.apache.amber.oauth2.client.response.OAuthClientResponse;
+import org.apache.amber.oauth2.common.exception.OAuthProblemException;
+import org.apache.amber.oauth2.common.exception.OAuthSystemException;
+import org.apache.amber.oauth2.common.message.types.GrantType;
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.context.ConfigurationContext;
+import org.apache.axis2.transport.http.HTTPConstants;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.manager.internal.DataHolder;
+import org.apache.stratos.manager.utils.CartridgeConstants;
+import org.wso2.carbon.base.ServerConfiguration;
+import org.wso2.carbon.identity.application.common.model.xsd.InboundAuthenticationRequestConfig;
+import org.wso2.carbon.identity.application.common.model.xsd.OutboundProvisioningConfig;
+import org.wso2.carbon.identity.application.common.model.xsd.Property;
+import org.wso2.carbon.identity.application.common.model.xsd.ServiceProvider;
+import org.wso2.carbon.identity.application.mgt.stub.IdentityApplicationManagementServiceIdentityApplicationManagementException;
+import org.wso2.carbon.identity.application.mgt.stub.IdentityApplicationManagementServiceStub;
+import org.wso2.carbon.identity.oauth.stub.OAuthAdminServiceException;
+import org.wso2.carbon.identity.oauth.stub.dto.OAuthConsumerAppDTO;
+import org.wso2.carbon.utils.CarbonUtils;
+
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class IdentityApplicationManagementServiceClient {
+
+    private static final Log log = LogFactory.getLog(IdentityApplicationManagementServiceClient.class);
+    private static final String ID_TOKEN = "id_token";
+
+    private static IdentityApplicationManagementServiceClient serviceClient;
+    private final IdentityApplicationManagementServiceStub stub;
+
+    public IdentityApplicationManagementServiceClient(String epr) throws AxisFault {
+
+
+        String autosclaerSocketTimeout =
+                System.getProperty(CartridgeConstants.AUTOSCALER_SOCKET_TIMEOUT) == null ? "300000" : System.getProperty(CartridgeConstants.AUTOSCALER_SOCKET_TIMEOUT);
+        String autosclaerConnectionTimeout =
+                System.getProperty(CartridgeConstants.AUTOSCALER_CONNECTION_TIMEOUT) == null ? "300000" : System.getProperty(CartridgeConstants.AUTOSCALER_CONNECTION_TIMEOUT);
+
+        ConfigurationContext clientConfigContext = DataHolder.getClientConfigContext();
+        try {
+            ServerConfiguration serverConfig = CarbonUtils.getServerConfiguration();
+            String trustStorePath = serverConfig.getFirstProperty("Security.TrustStore.Location");
+            String trustStorePassword = serverConfig.getFirstProperty("Security.TrustStore.Password");
+            String type = serverConfig.getFirstProperty("Security.TrustStore.Type");
+
+            System.setProperty("javax.net.ssl.trustStore", trustStorePath);
+            System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
+            System.setProperty("javax.net.ssl.trustStoreType", type);
+
+            stub = new IdentityApplicationManagementServiceStub(clientConfigContext, epr);
+            stub._getServiceClient().getOptions().setProperty(HTTPConstants.SO_TIMEOUT, new Integer(autosclaerSocketTimeout));
+            stub._getServiceClient().getOptions().setProperty(HTTPConstants.CONNECTION_TIMEOUT, new Integer(autosclaerConnectionTimeout));
+            Utility.setAuthHeaders(stub._getServiceClient(), "admin");
+
+        } catch (AxisFault axisFault) {
+            String msg = "Failed to initiate identity service client. " + axisFault.getMessage();
+            log.error(msg, axisFault);
+            throw new AxisFault(msg, axisFault);
+        }
+    }
+
+    public static IdentityApplicationManagementServiceClient getServiceClient() throws AxisFault {
+        if (serviceClient == null) {
+            synchronized (IdentityApplicationManagementServiceClient.class) {
+                if (serviceClient == null) {
+                    serviceClient = new IdentityApplicationManagementServiceClient(System.getProperty(CartridgeConstants.IDENTITY_SERVICE_URL) + "/services/IdentityApplicationManagementService");
+                }
+            }
+        }
+        return serviceClient;
+    }
+
+    public String createServiceProvider(String appName, String spName, String compositeAppId) throws RemoteException, OAuthAdminServiceException {
+        OAuthConsumerAppDTO oAuthApplication = null;
+        String accessToken = null;
+
+        oAuthApplication = oAuthAdminServiceClient.getServiceClient().getOAuthApplication(appName);
+
+        if(oAuthApplication == null){
+            return null;
+        }
+
+        String consumerKey = oAuthApplication.getOauthConsumerKey();
+        String consumerSecret = oAuthApplication.getOauthConsumerSecret();
+
+        ServiceProvider serviceProvider = new ServiceProvider();
+        serviceProvider.setApplicationName(spName);
+
+        try {
+            stub.createApplication(serviceProvider);
+        } catch (IdentityApplicationManagementServiceIdentityApplicationManagementException e) {
+            e.printStackTrace();
+        }
+        try {
+            serviceProvider = stub.getApplication(spName);
+        } catch (IdentityApplicationManagementServiceIdentityApplicationManagementException e) {
+            e.printStackTrace();
+        }
+
+        serviceProvider.setOutboundProvisioningConfig(new OutboundProvisioningConfig());
+
+        List<InboundAuthenticationRequestConfig> authRequestList = new ArrayList<InboundAuthenticationRequestConfig>();
+
+
+        if (consumerKey != null) {
+            InboundAuthenticationRequestConfig opicAuthenticationRequest =
+                    new InboundAuthenticationRequestConfig();
+            opicAuthenticationRequest.setInboundAuthKey(consumerKey);
+            opicAuthenticationRequest.setInboundAuthType("oauth2");
+            if (consumerSecret != null && !consumerSecret.isEmpty()) {
+                Property property = new Property();
+                property.setName("oauthConsumerSecret");
+                property.setValue(consumerSecret);
+                Property[] properties = {property};
+                opicAuthenticationRequest.setProperties(properties);
+            }
+            authRequestList.add(opicAuthenticationRequest);
+        }
+
+        String passiveSTSRealm = spName;
+        if (passiveSTSRealm != null) {
+            InboundAuthenticationRequestConfig opicAuthenticationRequest =
+                    new InboundAuthenticationRequestConfig();
+            opicAuthenticationRequest.setInboundAuthKey(passiveSTSRealm);
+            opicAuthenticationRequest.setInboundAuthType("passivests");
+            authRequestList.add(opicAuthenticationRequest);
+        }
+
+        String openidRealm = spName;
+        if (openidRealm != null) {
+            InboundAuthenticationRequestConfig opicAuthenticationRequest =
+                    new InboundAuthenticationRequestConfig();
+            opicAuthenticationRequest.setInboundAuthKey(openidRealm);
+            opicAuthenticationRequest.setInboundAuthType("openid");
+            authRequestList.add(opicAuthenticationRequest);
+        }
+
+        if (authRequestList.size() > 0) {
+            serviceProvider.getInboundAuthenticationConfig()
+                    .setInboundAuthenticationRequestConfigs(authRequestList.toArray(new InboundAuthenticationRequestConfig[authRequestList.size()]));
+        }
+
+        try {
+            stub.updateApplication(serviceProvider);
+        } catch (IdentityApplicationManagementServiceIdentityApplicationManagementException e) {
+            e.printStackTrace();
+        }
+
+        accessToken = getIdToken(compositeAppId, accessToken, consumerKey, consumerSecret);
+        return accessToken;
+    }
+
+    private String getIdToken(String compositeAppId, String accessToken, String consumerKey, String consumerSecret) {
+        String tokenEndpoint = System.getProperty(CartridgeConstants.IDENTITY_SERVICE_URL) + "oauth2/token";
+        try {
+            OAuthClientRequest accessRequest = OAuthClientRequest.tokenLocation(tokenEndpoint)
+                    .setGrantType(GrantType.CLIENT_CREDENTIALS)
+                    .setClientId(consumerKey)
+                    .setClientSecret(consumerSecret)
+                    .setScope(compositeAppId)
+                    .buildBodyMessage();
+            OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
+
+            OAuthClientResponse oAuthResponse = oAuthClient.accessToken(accessRequest);
+            accessToken = oAuthResponse.getParam(ID_TOKEN);
+
+        } catch (OAuthSystemException e) {
+            e.printStackTrace();
+        } catch (OAuthProblemException e) {
+            e.printStackTrace();
+        }
+        return accessToken;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/client/Utility.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/client/Utility.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/client/Utility.java
new file mode 100644
index 0000000..59f4230
--- /dev/null
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/client/Utility.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.stratos.manager.client;
+
+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.axiom.util.base64.Base64Utils;
+import org.apache.axis2.client.ServiceClient;
+import org.apache.axis2.transport.http.HTTPConstants;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.base.MultitenantConstants;
+import org.wso2.carbon.core.util.KeyStoreManager;
+
+import java.security.SignatureException;
+import java.security.interfaces.RSAPrivateKey;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Utility {
+    public static final String SIGNED_JWT_AUTH_USERNAME = "Username";
+    public static final String BEARER = "Bearer";
+    private static final Log log = LogFactory.getLog(Utility.class);
+
+    /**
+     * Set Auth headers to service client. Singed JWT authentication handler expect username
+     * as a claim in order to validate the user. This is an alternative to mutual auth.
+     *
+     * @param serviceClient Service client.
+     * @param username username which is set in header.
+     */
+
+    public static void setAuthHeaders(ServiceClient serviceClient, String username) {
+        List headerList = new ArrayList();
+        Header header = new Header();
+        header.setName(HTTPConstants.HEADER_AUTHORIZATION);
+        header.setValue(getAuthHeader(username));
+        headerList.add(header);
+        serviceClient.getOptions().setProperty(HTTPConstants.HTTP_HEADERS, headerList);
+    }
+
+    public static String getAuthHeader(String username) throws RuntimeException {
+
+        KeyStoreManager keyStoreManager;
+        keyStoreManager = KeyStoreManager.getInstance(MultitenantConstants.SUPER_TENANT_ID);
+        try {
+            keyStoreManager.getDefaultPrimaryCertificate();
+            JWSSigner signer = new RSASSASigner((RSAPrivateKey) keyStoreManager.getDefaultPrivateKey());
+            JWTClaimsSet claimsSet = new JWTClaimsSet();
+            claimsSet.setClaim(SIGNED_JWT_AUTH_USERNAME, username);
+            SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS512), claimsSet);
+            signedJWT.sign(signer);
+
+            return BEARER + " " + Base64Utils.encode(signedJWT.serialize().getBytes());
+        } catch (SignatureException e) {
+            String msg = "Failed to sign with signature instance";
+            log.error(msg, e);
+            throw new RuntimeException(msg, e);
+        } catch (Exception e) {
+            String msg = "Failed to get primary default certificate";
+            log.error(msg, e);
+            throw new RuntimeException(msg, e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/client/oAuthAdminServiceClient.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/client/oAuthAdminServiceClient.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/client/oAuthAdminServiceClient.java
new file mode 100644
index 0000000..febf8c7
--- /dev/null
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/client/oAuthAdminServiceClient.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.stratos.manager.client;
+
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.context.ConfigurationContext;
+import org.apache.axis2.transport.http.HTTPConstants;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.manager.internal.DataHolder;
+import org.apache.stratos.manager.utils.CartridgeConstants;
+import org.wso2.carbon.base.ServerConfiguration;
+import org.wso2.carbon.identity.oauth.stub.OAuthAdminServiceException;
+import org.wso2.carbon.identity.oauth.stub.OAuthAdminServiceStub;
+import org.wso2.carbon.identity.oauth.stub.dto.OAuthConsumerAppDTO;
+import org.wso2.carbon.utils.CarbonUtils;
+
+import java.rmi.RemoteException;
+
+public class oAuthAdminServiceClient {
+
+    public static final String GRANT_TYPE = "client-credentials";
+    private static final Log log = LogFactory.getLog(oAuthAdminServiceClient.class);
+    private static final String OAUTH_2_0 = "oauth-2.0";
+    private static oAuthAdminServiceClient serviceClient;
+    private final OAuthAdminServiceStub stub;
+
+    public oAuthAdminServiceClient(String epr) throws AxisFault {
+
+        String autosclaerSocketTimeout =
+                System.getProperty(CartridgeConstants.AUTOSCALER_SOCKET_TIMEOUT) == null ? "300000" : System.getProperty(CartridgeConstants.AUTOSCALER_SOCKET_TIMEOUT);
+        String autosclaerConnectionTimeout =
+                System.getProperty(CartridgeConstants.AUTOSCALER_CONNECTION_TIMEOUT) == null ? "300000" : System.getProperty(CartridgeConstants.AUTOSCALER_CONNECTION_TIMEOUT);
+
+        ConfigurationContext clientConfigContext = DataHolder.getClientConfigContext();
+        try {
+            ServerConfiguration serverConfig = CarbonUtils.getServerConfiguration();
+            String trustStorePath = serverConfig.getFirstProperty("Security.TrustStore.Location");
+            String trustStorePassword = serverConfig.getFirstProperty("Security.TrustStore.Password");
+            String type = serverConfig.getFirstProperty("Security.TrustStore.Type");
+            System.setProperty("javax.net.ssl.trustStore", trustStorePath);
+            System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
+            System.setProperty("javax.net.ssl.trustStoreType", type);
+
+            stub = new OAuthAdminServiceStub(clientConfigContext, epr);
+            stub._getServiceClient().getOptions().setProperty(HTTPConstants.SO_TIMEOUT, new Integer(autosclaerSocketTimeout));
+            stub._getServiceClient().getOptions().setProperty(HTTPConstants.CONNECTION_TIMEOUT, new Integer(autosclaerConnectionTimeout));
+            Utility.setAuthHeaders(stub._getServiceClient(), "admin");
+
+        } catch (AxisFault axisFault) {
+            String msg = "Failed to initiate identity service client. " + axisFault.getMessage();
+            log.error(msg, axisFault);
+            throw new AxisFault(msg, axisFault);
+        }
+    }
+
+    public static oAuthAdminServiceClient getServiceClient() throws AxisFault {
+        if (serviceClient == null) {
+            synchronized (oAuthAdminServiceClient.class) {
+                if (serviceClient == null) {
+                    serviceClient = new oAuthAdminServiceClient(System.getProperty(CartridgeConstants.IDENTITY_SERVICE_URL) + "/services/OAuthAdminService");
+                }
+            }
+        }
+        return serviceClient;
+    }
+
+    public void registerOauthApplication(String appName) throws RemoteException, OAuthAdminServiceException {
+        OAuthConsumerAppDTO oAuthConsumerDTO = new OAuthConsumerAppDTO();
+        oAuthConsumerDTO.setApplicationName(appName);
+        oAuthConsumerDTO.setOAuthVersion(OAUTH_2_0);
+        oAuthConsumerDTO.setGrantTypes(GRANT_TYPE);
+        stub.registerOAuthApplicationData(oAuthConsumerDTO);
+    }
+
+    public OAuthConsumerAppDTO getOAuthApplication(String name) throws RemoteException, OAuthAdminServiceException {
+        return stub.getOAuthApplicationDataByAppName(name);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/CartridgeConstants.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/CartridgeConstants.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/CartridgeConstants.java
index 2c6014e..89a41ca 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/CartridgeConstants.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/CartridgeConstants.java
@@ -21,6 +21,7 @@ package org.apache.stratos.manager.utils;
 
 public class CartridgeConstants {
 	public static final String AUTOSCALER_SERVICE_URL = "autoscaler.service.url";
+	public static final String IDENTITY_SERVICE_URL = "identity.service.url";
     public static final String CLOUD_CONTROLLER_SERVICE_URL = "cloud.controller.service.url";
     public static final String ALIAS_NAMESPACE ="http://org.wso2.securevault/configuration";
     public static final String ALIAS_LOCALPART ="secretAlias";

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/components/org.apache.stratos.metadataservice/src/main/java/org/apache/stratos/metadataservice/handlers/OAuthHandler.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.metadataservice/src/main/java/org/apache/stratos/metadataservice/handlers/OAuthHandler.java b/components/org.apache.stratos.metadataservice/src/main/java/org/apache/stratos/metadataservice/handlers/OAuthHandler.java
index 4dc5573..39ab236 100644
--- a/components/org.apache.stratos.metadataservice/src/main/java/org/apache/stratos/metadataservice/handlers/OAuthHandler.java
+++ b/components/org.apache.stratos.metadataservice/src/main/java/org/apache/stratos/metadataservice/handlers/OAuthHandler.java
@@ -18,17 +18,22 @@
  */
 package org.apache.stratos.metadataservice.handlers;
 
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Response;
-
+import com.nimbusds.jose.JWSVerifier;
+import com.nimbusds.jose.crypto.RSASSAVerifier;
+import com.nimbusds.jwt.SignedJWT;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.cxf.jaxrs.impl.HttpHeadersImpl;
 import org.apache.cxf.jaxrs.model.ClassResourceInfo;
 import org.apache.cxf.message.Message;
 import org.apache.stratos.metadataservice.context.AuthenticationContext;
-import org.apache.stratos.metadataservice.oauth2.ValidationServiceClient;
-import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO;
+import org.wso2.carbon.base.MultitenantConstants;
+import org.wso2.carbon.core.util.KeyStoreManager;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import java.security.interfaces.RSAPublicKey;
+
 
 /**
  * This class responsible for OAuth based authentication/authorization. A client
@@ -37,59 +42,91 @@ import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO
  * OAuthTokenValidation endpoint of the provider.
  */
 public class OAuthHandler extends AbstractAuthenticationAuthorizationHandler {
-	private static Log log = LogFactory.getLog(OAuthHandler.class);
-	private static String SUPPORTED_AUTHENTICATION_TYPE = "Bearer";
-	private static String oauthValidationEndpoint;
-	private static String username;
-	private static String password;
+    public static final String BEARER = "Bearer ";
+    public static final String APPLICATION = "application";
+    private static Log log = LogFactory.getLog(OAuthHandler.class);
+    private static String SUPPORTED_AUTHENTICATION_TYPE = "Bearer";
+    private static String oauthValidationEndpoint;
+    private static String username;
+    private static String password;
+
+    public void setOauthValidationEndpoint(String oauthValidationEndpoint) {
+        OAuthHandler.oauthValidationEndpoint = oauthValidationEndpoint;
+    }
+
+    public void setUsername(String username) {
+        OAuthHandler.username = username;
+    }
+
+    public void setPassword(String password) {
+        OAuthHandler.password = password;
+    }
+
+    @Override
+    public boolean canHandle(String authHeaderPrefix) {
+        return SUPPORTED_AUTHENTICATION_TYPE.equals(authHeaderPrefix);
+    }
+
+    @Override
+    public Response handle(Message message, ClassResourceInfo classResourceInfo) {
+        try {
+            HttpHeaders httpHeaders = new HttpHeadersImpl(message);
+            String header = httpHeaders.getRequestHeaders().getFirst("Authorization");
+            // if the authorization token has Bearer..
+            if (header.startsWith(BEARER)) {
+                String accessToken = header.substring(7).trim();
+                boolean valid;
+                String appId = extractAppIdFromIdToken(accessToken);
+                String requestUrl = (String) message.get(Message.REQUEST_URI);
+                String basePath = (String) message.get(Message.BASE_PATH);
+                String requestedAppId = extractApplicationIdFromUrl(requestUrl, basePath);
+
+                if(org.apache.commons.lang3.StringUtils.isEmpty(appId) || org.apache.commons.lang3.StringUtils.isEmpty(requestedAppId)){
+                    valid = false;
+                }else{
+                    valid = appId.equals(requestedAppId);
+                }
 
-	public void setOauthValidationEndpoint(String oauthValidationEndpoint) {
-		OAuthHandler.oauthValidationEndpoint = oauthValidationEndpoint;
-	}
+                if (!valid) {
+                    return Response.status(Response.Status.FORBIDDEN).build();
+                }
+            }
+        } catch (Exception e) {
+            log.error("Error while validating access token", e);
+            return Response.status(Response.Status.FORBIDDEN).build();
+        }
 
-	public void setUsername(String username) {
-		OAuthHandler.username = username;
-	}
+        AuthenticationContext.setAuthenticated(true);
+        return null;
+    }
 
-	public void setPassword(String password) {
-		OAuthHandler.password = password;
-	}
+    private String extractApplicationIdFromUrl(String url, String basePath) {
+        String appId = null;
+        String segments[] = url.split("/");
+        for (int i = 0; i < segments.length; i++) {
+            if (APPLICATION.equals(segments[i])) {
+                appId = segments[i + 1];
+                break;
+            }
+        }
+        return appId;
+    }
 
-	@Override
-	public boolean canHandle(String authHeaderPrefix) {
-		return SUPPORTED_AUTHENTICATION_TYPE.equals(authHeaderPrefix);
-	}
+    private String extractAppIdFromIdToken(String token) {
+        String appId = null;
+        KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(MultitenantConstants.SUPER_TENANT_ID);
+        try {
+            keyStoreManager.getDefaultPrimaryCertificate();
+            JWSVerifier verifier =
+                    new RSASSAVerifier((RSAPublicKey) keyStoreManager.getDefaultPublicKey());
+            SignedJWT jwsObject = SignedJWT.parse(token);
+            if (jwsObject.verify(verifier)) {
+               appId = jwsObject.getJWTClaimsSet().getStringClaim("appId");
+            }
 
-	@Override
-	public Response handle(Message message, ClassResourceInfo classResourceInfo) {
-		try {
-			OAuth2TokenValidationResponseDTO respDTO;
-			ValidationServiceClient validationServiceClient =
-			                                                  new ValidationServiceClient(
-			                                                                              oauthValidationEndpoint,
-			                                                                              username,
-			                                                                              password);
-			HttpHeaders httpHeaders = new HttpHeadersImpl(message);
-			String header = httpHeaders.getRequestHeaders().getFirst("Authorization");
-			// if the authorization token has Bearer..
-			if (header.startsWith("Bearer ")) {
-				String accessToken = header.substring(7).trim();
-				respDTO = validationServiceClient.validateAuthenticationRequest(accessToken); // TODO
-				                                                                              // :
-				                                                                              // send
-				                                                                              // scope
-				                                                                              // params
-				boolean valid = respDTO.getValid();
-				if (!valid) {
-					// authorization failure..
-					return Response.status(Response.Status.FORBIDDEN).build();
-				}
-			}
-		} catch (Exception e) {
-			log.error("Error while validating access token", e);
-			return Response.status(Response.Status.FORBIDDEN).build();
-		}
-		AuthenticationContext.setAuthenticated(true);
-		return null;
-	}
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return appId;
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/components/org.apache.stratos.metadataservice/src/main/webapp/stratosmetadataservice/WEB-INF/cxf-servlet.xml
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.metadataservice/src/main/webapp/stratosmetadataservice/WEB-INF/cxf-servlet.xml b/components/org.apache.stratos.metadataservice/src/main/webapp/stratosmetadataservice/WEB-INF/cxf-servlet.xml
index e015301..25e97fb 100644
--- a/components/org.apache.stratos.metadataservice/src/main/webapp/stratosmetadataservice/WEB-INF/cxf-servlet.xml
+++ b/components/org.apache.stratos.metadataservice/src/main/webapp/stratosmetadataservice/WEB-INF/cxf-servlet.xml
@@ -35,9 +35,10 @@
 			<ref bean="genericExceptionHandler"/>
             <ref bean="jsonProvider"/>
             <ref bean="exceptionHandler"/>
+	    <ref bean="OAuthFilter"/>
             <ref bean="basicAuthenticationFilter"/>
             <ref bean="sessionAuthenticationFilter"/>
-            <ref bean="authorizationFilter"/>
+            <!--<ref bean="authorizationFilter"/>-->
         </jaxrs:providers>
     </jaxrs:server>
 

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/api/StratosApiV41Utils.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/api/StratosApiV41Utils.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/api/StratosApiV41Utils.java
index fe7b997..6290500 100644
--- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/api/StratosApiV41Utils.java
+++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/api/StratosApiV41Utils.java
@@ -34,6 +34,8 @@ import org.apache.stratos.cloud.controller.stub.domain.CartridgeInfo;
 import org.apache.stratos.common.Property;
 import org.apache.stratos.manager.client.AutoscalerServiceClient;
 import org.apache.stratos.manager.client.CloudControllerServiceClient;
+import org.apache.stratos.manager.client.IdentityApplicationManagementServiceClient;
+import org.apache.stratos.manager.client.oAuthAdminServiceClient;
 import org.apache.stratos.manager.composite.application.beans.ApplicationDefinition;
 import org.apache.stratos.manager.deploy.cartridge.CartridgeDeploymentManager;
 import org.apache.stratos.manager.deploy.service.Service;
@@ -79,6 +81,7 @@ import org.apache.stratos.rest.endpoint.bean.repositoryNotificationInfoBean.Payl
 import org.apache.stratos.rest.endpoint.bean.subscription.domain.SubscriptionDomainBean;
 import org.apache.stratos.rest.endpoint.bean.util.converter.PojoConverter;
 import org.apache.stratos.rest.endpoint.exception.RestAPIException;
+import org.wso2.carbon.identity.oauth.stub.OAuthAdminServiceException;
 
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
@@ -1964,4 +1967,23 @@ public class StratosApiV41Utils {
         }
 
     }
+
+    public static void createToken() throws RestAPIException {
+        String appName = "testudara" + Math.random();
+        String compositeAppId = "app1";
+        try {
+            oAuthAdminServiceClient.getServiceClient().registerOauthApplication(appName);
+        } catch (RemoteException e) {
+           throw new RestAPIException(e);
+        } catch (OAuthAdminServiceException e) {
+            throw new RestAPIException(e);
+        }
+        try {
+            IdentityApplicationManagementServiceClient.getServiceClient().createServiceProvider(appName, appName, compositeAppId);
+        } catch (RemoteException e) {
+            throw new RestAPIException(e);
+        } catch (OAuthAdminServiceException e) {
+            e.printStackTrace();
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/components/pom.xml
----------------------------------------------------------------------
diff --git a/components/pom.xml b/components/pom.xml
index ce08ffc..997588a 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -104,6 +104,8 @@
         <module>org.apache.stratos.rest.endpoint</module>
         <!-- Stratos manager styles bundle -->
         <module>org.apache.stratos.manager.styles</module>
+
+        <module>org.apache.stratos.custom.handlers</module>
 		
 	<module>org.apache.stratos.metadataservice</module>
 	<!-- meta data client -->

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/features/common/org.apache.stratos.metadata.client.feature/pom.xml
----------------------------------------------------------------------
diff --git a/features/common/org.apache.stratos.metadata.client.feature/pom.xml b/features/common/org.apache.stratos.metadata.client.feature/pom.xml
index 09857d0..19c679c 100644
--- a/features/common/org.apache.stratos.metadata.client.feature/pom.xml
+++ b/features/common/org.apache.stratos.metadata.client.feature/pom.xml
@@ -19,7 +19,8 @@
 
 -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
     <parent>
         <groupId>org.apache.stratos</groupId>
@@ -32,7 +33,7 @@
     <packaging>pom</packaging>
     <name>Apache Stratos - Metadata client Feature</name>
     <url>http://apache.org</url>
-    <description />
+    <description/>
 
     <dependencies>
         <dependency>
@@ -40,7 +41,7 @@
             <artifactId>gson</artifactId>
             <version>${gson2.version}</version>
         </dependency>
-<dependency>
+        <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpasyncclient</artifactId>
             <version>4.0-beta3</version>
@@ -50,13 +51,12 @@
             <artifactId>httpclient-osgi</artifactId>
             <version>4.3.5</version>
         </dependency>
-	<dependency>
+        <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpclient</artifactId>
             <version>4.3.5</version>
         </dependency>
-
-	<dependency>
+        <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpcore</artifactId>
             <version>4.3.2</version>
@@ -96,7 +96,8 @@
                                 </properties>
                             </adviceFile>
                             <bundles>
-                                <bundleDef>org.apache.stratos:org.apache.stratos.metadata.client:${project.version}</bundleDef>
+                                <bundleDef>org.apache.stratos:org.apache.stratos.metadata.client:${project.version}
+                                </bundleDef>
                                 <bundleDef>com.google.code.gson:gson:${gson2.version}</bundleDef>
                                 <bundleDef>org.apache.commons:commons-lang3:3.1</bundleDef>
                                 <bundleDef>org.apache.httpcomponents:httpclient-osgi:4.3.5</bundleDef>

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/features/common/pom.xml
----------------------------------------------------------------------
diff --git a/features/common/pom.xml b/features/common/pom.xml
index b2a4481..1f9ab37 100644
--- a/features/common/pom.xml
+++ b/features/common/pom.xml
@@ -27,11 +27,12 @@
     <modelVersion>4.0.0</modelVersion>
     <artifactId>common.features</artifactId>
     <packaging>pom</packaging>
-    <name>Apache Stratos - Metadata Client Module</name>
+    <name>Apache Stratos - Common  Module</name>
     <url>http://apache.org</url>
 
     <modules>
         <module>org.apache.stratos.metadata.client.feature</module>
+        <module>org.apache.stratos.custom.handlers.feature</module>
     </modules>
 </project>
 

http://git-wip-us.apache.org/repos/asf/stratos/blob/c0651601/products/stratos/modules/p2-profile-gen/pom.xml
----------------------------------------------------------------------
diff --git a/products/stratos/modules/p2-profile-gen/pom.xml b/products/stratos/modules/p2-profile-gen/pom.xml
index f5cdbfd..35c4b48 100644
--- a/products/stratos/modules/p2-profile-gen/pom.xml
+++ b/products/stratos/modules/p2-profile-gen/pom.xml
@@ -333,6 +333,7 @@
                                 <featureArtifactDef>org.wso2.carbon:org.wso2.carbon.cassandra.common.feature:${carbon.platform.version}</featureArtifactDef>
 				<!-- Common features -->
 				<featureArtifactDef>org.apache.stratos:org.apache.stratos.metadata.client.feature:${project.version}</featureArtifactDef>
+				<featureArtifactDef>org.apache.stratos:org.apache.stratos.custom.handlers.feature:${project.version}</featureArtifactDef>
                             </featureArtifacts>
                         </configuration>
                     </execution>
@@ -561,6 +562,10 @@
                                      <id>org.wso2.carbon.user.mgt.feature.group</id>
 				     <version>${carbon.platform.patch.version.4.2.1}</version>
                                 </feature>
+				<feature>
+                                     <id>org.apache.stratos.custom.handlers.feature.group</id>
+				     <version>${project.version}</version>
+                                </feature>
                             </features>
                         </configuration>
                     </execution>
@@ -997,6 +1002,10 @@
                                     <id>org.apache.stratos.metadata.client.feature.group</id>
                                     <version>${project.version}</version>
                                 </feature>
+				<feature>
+                                    <id>org.apache.stratos.custom.handlers.feature.group</id>
+                                    <version>${project.version}</version>
+                                </feature>
 
                             </features>
                         </configuration>