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>