diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml index 265570cac2..bc2360aa32 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml @@ -46,15 +46,16 @@ ${project.artifactId} ${project.artifactId} org.wso2.carbon.webapp.authenticator.framework.internal.WebappAuthenticatorFrameworkBundleActivator - org.wso2.carbon.tomcat.patch + org.wso2.carbon.webapp.authenticator.framework.internal + * !org.wso2.carbon.webapp.authenticator.framework.internal, org.wso2.carbon.webapp.authenticator.framework.* - tomcat + diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/AuthenticationFrameworkUtil.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/AuthenticationFrameworkUtil.java new file mode 100644 index 0000000000..c0728d5c9a --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/AuthenticationFrameworkUtil.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * you may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.webapp.authenticator.framework; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.axiom.om.OMNamespace; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Document; +import org.wso2.carbon.apimgt.api.APIManagementException; +import org.wso2.carbon.apimgt.core.APIManagerErrorConstants; +import org.wso2.carbon.apimgt.core.authenticate.APITokenValidator; +import org.wso2.carbon.apimgt.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.identity.base.IdentityException; +import org.wso2.carbon.identity.core.util.IdentityUtil; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; +import java.io.IOException; + +public class AuthenticationFrameworkUtil { + + private static final Log log = LogFactory.getLog(AuthenticationFrameworkUtil.class); + + public static void handleNoMatchAuthScheme(Request request, Response response, String httpVerb, String version, + String context) { + String msg = "Resource is not matched for HTTP Verb: '" + httpVerb + "', API context: '" + context + + "', Version: '" + version + "' and RequestURI: '" + request.getRequestURI() + "'"; + handleResponse(request, response, HttpServletResponse.SC_FORBIDDEN, msg); + } + + public static boolean doAuthenticate( + String context, String version, String accessToken, String requiredAuthenticationLevel, + String clientDomain) throws APIManagementException, AuthenticationException { + + if (APIConstants.AUTH_NO_AUTHENTICATION.equals(requiredAuthenticationLevel)) { + return true; + } + APITokenValidator tokenValidator = new APITokenValidator(); + APIKeyValidationInfoDTO apiKeyValidationDTO = tokenValidator.validateKey(context, version, accessToken, + requiredAuthenticationLevel, clientDomain); + if (apiKeyValidationDTO.isAuthorized()) { + String userName = apiKeyValidationDTO.getEndUserName(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(userName); + try { + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId( + IdentityUtil.getTenantIdOFUser(userName)); + } catch (IdentityException e) { + throw new AuthenticationException("Error occurred while retrieving the tenant ID of user '" + + userName + "'", e); + } + } else { + throw new AuthenticationException(apiKeyValidationDTO.getValidationStatus(), + "Access failure for API: " + context + ", version: " + + version + " with key: " + accessToken); + } + return false; + } + + public static void handleResponse(Request request, Response response, int statusCode, String payload) { + response.setStatus(statusCode); + String targetResponseContentType = + request.getHeader(Constants.HTTPHeaders.HEADER_HTTP_ACCEPT); + if (targetResponseContentType != null && !"".equals(targetResponseContentType) && + !Constants.ContentTypes.CONTENT_TYPE_ANY.equals(targetResponseContentType)) { + response.setContentType(targetResponseContentType); + } else { + response.setContentType(Constants.ContentTypes.CONTENT_TYPE_APPLICATION_XML); + } + response.setCharacterEncoding("UTF-8"); + try { + response.getWriter().write(payload); + } catch (IOException e) { + log.error("Error occurred while sending faulty response back to the client", e); + } + } + + public static Document convertToDocument(File file) throws AuthenticatorFrameworkException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + return docBuilder.parse(file); + } catch (Exception e) { + throw new AuthenticatorFrameworkException("Error occurred while parsing file, while converting " + + "to a org.w3c.dom.Document", e); + } + } + +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/AuthenticatorFrameworkException.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/AuthenticatorFrameworkException.java new file mode 100644 index 0000000000..61d08dc1db --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/AuthenticatorFrameworkException.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.wso2.carbon.webapp.authenticator.framework; + +public class AuthenticatorFrameworkException extends Exception { + + private static final long serialVersionUID = -3151279311229070297L; + + private String errorMessage; + private int errorCode; + + public AuthenticatorFrameworkException(int errorCode, String message) { + super(message); + this.errorCode = errorCode; + } + + public AuthenticatorFrameworkException(int errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = errorCode; + } + + public int getErrorCode() { + return errorCode; + } + + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public AuthenticatorFrameworkException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public AuthenticatorFrameworkException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public AuthenticatorFrameworkException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public AuthenticatorFrameworkException() { + super(); + } + + public AuthenticatorFrameworkException(Throwable cause) { + super(cause); + } + +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/BasicAuthAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/BasicAuthAuthenticator.java deleted file mode 100644 index cdff89b5ff..0000000000 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/BasicAuthAuthenticator.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.wso2.carbon.webapp.authenticator.framework; - -import org.apache.catalina.connector.Request; - -public class BasicAuthAuthenticator implements WebappAuthenticator { - - private static final String BASIC_AUTH_AUTHENTICATOR = "BasicAuthAuthenticator"; - - private String username; - private String password; - - public BasicAuthAuthenticator(String username, String password) { - this.username = username; - this.password = password; - } - - @Override - public boolean isAuthenticated(Request request) { - return false; - } - - @Override - public Status authenticate(Request request) { - return Status.CONTINUE; - } - - @Override - public String getAuthenticatorName() { - return BasicAuthAuthenticator.BASIC_AUTH_AUTHENTICATOR; - } - -} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/HandlerConstants.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/Constants.java similarity index 54% rename from components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/HandlerConstants.java rename to components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/Constants.java index fa1ac7dbe4..a046c5280b 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/HandlerConstants.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/Constants.java @@ -17,11 +17,27 @@ */ package org.wso2.carbon.webapp.authenticator.framework; -public class HandlerConstants { - - public static final String HEADER_AUTHORIZATION = "Authorization"; - public static final String TOKEN_NAME_BEARER = "Bearer"; +public final class Constants { + public static final String AUTHORIZATION_HEADER_PREFIX_BEARER = "Bearer"; public static final String NO_MATCHING_AUTH_SCHEME = "noMatchedAuthScheme"; + public static final class HTTPHeaders { + private HTTPHeaders() { + throw new AssertionError(); + } + + public static final String HEADER_HTTP_ACCEPT = "Accept"; + public static final String HEADER_HTTP_AUTHORIZATION = "Authorization"; + } + + public static final class ContentTypes { + private ContentTypes() { + throw new AssertionError(); + } + + public static final String CONTENT_TYPE_ANY = "*/*"; + public static final String CONTENT_TYPE_APPLICATION_XML = "application/xml"; + } + } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/HandlerUtil.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/HandlerUtil.java deleted file mode 100644 index 53f3a69164..0000000000 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/HandlerUtil.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * you may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.wso2.carbon.webapp.authenticator.framework; - -import org.apache.axiom.om.OMAbstractFactory; -import org.apache.axiom.om.OMElement; -import org.apache.axiom.om.OMFactory; -import org.apache.axiom.om.OMNamespace; -import org.apache.catalina.connector.Response; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.apimgt.api.APIManagementException; -import org.wso2.carbon.apimgt.core.APIManagerErrorConstants; -import org.wso2.carbon.apimgt.core.authenticate.APITokenValidator; -import org.wso2.carbon.apimgt.impl.APIConstants; -import org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO; -import org.wso2.carbon.context.PrivilegedCarbonContext; -import org.wso2.carbon.identity.base.IdentityException; -import org.wso2.carbon.identity.core.util.IdentityUtil; - -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; - -public class HandlerUtil { - - private static final Log log = LogFactory.getLog(HandlerUtil.class); - - /** - * Retrieve bearer token form the HTTP header - * @param bearerToken Bearer Token extracted out of the corresponding HTTP header - */ - public static String getAccessToken(String bearerToken) { - String accessToken = null; - String[] token = bearerToken.split(HandlerConstants.TOKEN_NAME_BEARER); - if (token.length > 1 && token[1] != null) { - accessToken = token[1].trim(); - } - return accessToken; - } - - public static String getAPIVersion(HttpServletRequest request) { - int contextStartsIndex = (request.getRequestURI()).indexOf(request.getContextPath()) + 1; - int length = request.getContextPath().length(); - String afterContext = (request.getRequestURI()).substring(contextStartsIndex + length); - int SlashIndex = afterContext.indexOf(("/")); - - if (SlashIndex != -1) { - return afterContext.substring(0, SlashIndex); - } else { - return afterContext; - } - } - - public static void handleNoMatchAuthSchemeCallForRestService(Response response,String httpVerb, String reqUri, - String version, String context ) { - String errMsg = "Resource is not matched for HTTP Verb " + httpVerb + ". API context " + context + - ",version " + version + ", request " + reqUri; - AuthenticationException e = - new AuthenticationException(APIManagerErrorConstants.API_AUTH_INCORRECT_API_RESOURCE, errMsg); - String faultPayload = getFaultPayload(e, APIManagerErrorConstants.API_SECURITY_NS, - APIManagerErrorConstants.API_SECURITY_NS_PREFIX).toString(); - handleRestFailure(response, faultPayload); - } - - public static boolean doAuthenticate(String context, String version, String accessToken, - String requiredAuthenticationLevel, String clientDomain) - throws APIManagementException, - AuthenticationException { - - if (APIConstants.AUTH_NO_AUTHENTICATION.equals(requiredAuthenticationLevel)) { - return true; - } - APITokenValidator tokenValidator = new APITokenValidator(); - APIKeyValidationInfoDTO apiKeyValidationDTO = tokenValidator.validateKey(context, version, accessToken, - requiredAuthenticationLevel, clientDomain); - if (apiKeyValidationDTO.isAuthorized()) { - String userName = apiKeyValidationDTO.getEndUserName(); - PrivilegedCarbonContext.getThreadLocalCarbonContext() - .setUsername(apiKeyValidationDTO.getEndUserName()); - try { - PrivilegedCarbonContext.getThreadLocalCarbonContext() - .setTenantId(IdentityUtil.getTenantIdOFUser(userName)); - } catch (IdentityException e) { - log.error("Error while retrieving Tenant Id", e); - return false; - } - return true; - } else { - throw new AuthenticationException(apiKeyValidationDTO.getValidationStatus(), - "Access failure for API: " + context + ", version: " + - version + " with key: " + accessToken); - } - } - - public static void handleRestFailure(Response response, String payload) { - response.setStatus(403); - response.setContentType("application/xml"); - response.setCharacterEncoding("UTF-8"); - try { - response.getWriter().write(payload); - } catch (IOException e) { - log.error("Error in sending fault response", e); - } - } - - public static OMElement getFaultPayload(AuthenticationException exception, String FaultNS, - String FaultNSPrefix) { - OMFactory fac = OMAbstractFactory.getOMFactory(); - OMNamespace ns = fac.createOMNamespace(FaultNS, FaultNSPrefix); - OMElement payload = fac.createOMElement("fault", ns); - - OMElement errorCode = fac.createOMElement("code", ns); - errorCode.setText(String.valueOf(exception.getErrorCode())); - OMElement errorMessage = fac.createOMElement("message", ns); - errorMessage.setText(APIManagerErrorConstants.getFailureMessage(exception.getErrorCode())); - OMElement errorDetail = fac.createOMElement("description", ns); - errorDetail.setText(exception.getMessage()); - - payload.addChild(errorCode); - payload.addChild(errorMessage); - payload.addChild(errorDetail); - return payload; - } - -} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/WebappAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/WebappAuthenticator.java index 7bcc084de7..4d0f5a0ddb 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/WebappAuthenticator.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/WebappAuthenticator.java @@ -19,6 +19,7 @@ package org.wso2.carbon.webapp.authenticator.framework; import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; public interface WebappAuthenticator { @@ -28,7 +29,7 @@ public interface WebappAuthenticator { boolean isAuthenticated(Request request); - Status authenticate(Request request); + Status authenticate(Request request, Response response); String getAuthenticatorName(); diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/WebappAuthenticatorFactory.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/WebappAuthenticatorFactory.java index 0dc842f233..02dcf44813 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/WebappAuthenticatorFactory.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/WebappAuthenticatorFactory.java @@ -23,45 +23,13 @@ import org.apache.catalina.util.Base64; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.CharChunk; import org.apache.tomcat.util.buf.MessageBytes; +import org.wso2.carbon.webapp.authenticator.framework.authenticator.BasicAuthAuthenticator; +import org.wso2.carbon.webapp.authenticator.framework.authenticator.OAuthAuthenticator; public class WebappAuthenticatorFactory { public static WebappAuthenticator getAuthenticator(Request request) { - MessageBytes authorization = request.getCoyoteRequest().getMimeHeaders().getValue("authorization"); - if (authorization != null) { - authorization.toBytes(); - ByteChunk authBC = authorization.getByteChunk(); - if (authBC.startsWithIgnoreCase("basic ", 0)) { - authBC.setOffset(authBC.getOffset() + 6); - - CharChunk authCC = authorization.getCharChunk(); - Base64.decode(authBC, authCC); - - String username; - String password = null; - - int colon = authCC.indexOf(':'); - if (colon < 0) { - username = authCC.toString(); - } else { - char[] buf = authCC.getBuffer(); - username = new String(buf, 0, colon); - password = new String(buf, colon + 1, authCC.getEnd() - colon - 1); - } - authBC.setOffset(authBC.getOffset() - 6); - return new BasicAuthAuthenticator(username, password); - } else if (authBC.startsWithIgnoreCase("bearer ", 0)) { - authBC.setOffset(authBC.getOffset() + 7); - - CharChunk authCC = authorization.getCharChunk(); - char[] buf = authCC.getBuffer(); - String bearer = new String(buf, 0, authCC.getEnd() - 1); - authBC.setOffset(authBC.getOffset() - 7); - return new OAuthAuthenticator(bearer); - } - } - throw new IllegalArgumentException("Failed to determine an appropriate authenticator to be used, based " + - "on the incoming request"); + return new OAuthAuthenticator(); } } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/WebappAuthenticatorFrameworkValve.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/WebappAuthenticatorFrameworkValve.java index fc86afa496..e14480d822 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/WebappAuthenticatorFrameworkValve.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/WebappAuthenticatorFrameworkValve.java @@ -18,29 +18,37 @@ */ package org.wso2.carbon.webapp.authenticator.framework; -import org.apache.axis2.context.MessageContext; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; -import org.apache.catalina.valves.ValveBase; -import org.wso2.carbon.core.services.authentication.CarbonServerAuthenticator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.wso2.carbon.tomcat.ext.valves.CarbonTomcatValve; import org.wso2.carbon.tomcat.ext.valves.CompositeValve; -import javax.servlet.ServletException; -import java.io.IOException; +import javax.servlet.http.HttpServletResponse; public class WebappAuthenticatorFrameworkValve extends CarbonTomcatValve { + private static final Log log = LogFactory.getLog(WebappAuthenticatorFrameworkValve.class); + @Override public void invoke(Request request, Response response, CompositeValve compositeValve) { WebappAuthenticator authenticator = WebappAuthenticatorFactory.getAuthenticator(request); - WebappAuthenticator.Status status = authenticator.authenticate(request); + WebappAuthenticator.Status status = authenticator.authenticate(request, response); + this.processResponse(request, response, compositeValve, status); + } + + private void processResponse(Request request, Response response, CompositeValve compositeValve, + WebappAuthenticator.Status status) { switch (status) { case SUCCESS: case CONTINUE: - getNext().invoke(request, response, compositeValve); + this.getNext().invoke(request, response, compositeValve); case FAILURE: - //do something + AuthenticationFrameworkUtil.handleResponse(request, response, HttpServletResponse.SC_UNAUTHORIZED, + "Failed to authorize the incoming request"); } } + + } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/BasicAuthAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/BasicAuthAuthenticator.java new file mode 100644 index 0000000000..60cc95f3bb --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/BasicAuthAuthenticator.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.wso2.carbon.webapp.authenticator.framework.authenticator; + +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.util.Base64; +import org.apache.tomcat.util.buf.ByteChunk; +import org.apache.tomcat.util.buf.CharChunk; +import org.apache.tomcat.util.buf.MessageBytes; +import org.wso2.carbon.webapp.authenticator.framework.WebappAuthenticator; + +public class BasicAuthAuthenticator implements WebappAuthenticator { + + private static final String BASIC_AUTH_AUTHENTICATOR = "BasicAuthAuthenticator"; + + @Override + public boolean isAuthenticated(Request request) { + return false; + } + + @Override + public Status authenticate(Request request, Response response) { + return Status.CONTINUE; + } + + @Override + public String getAuthenticatorName() { + return BasicAuthAuthenticator.BASIC_AUTH_AUTHENTICATOR; + } + + private Credentials getCredentials(Request request) { + Credentials credentials = null; + MessageBytes authorization = request.getCoyoteRequest().getMimeHeaders().getValue("authorization"); + if (authorization != null) { + authorization.toBytes(); + ByteChunk authBC = authorization.getByteChunk(); + if (authBC.startsWithIgnoreCase("basic ", 0)) { + authBC.setOffset(authBC.getOffset() + 6); + + CharChunk authCC = authorization.getCharChunk(); + Base64.decode(authBC, authCC); + + String username; + String password = null; + + int colon = authCC.indexOf(':'); + if (colon < 0) { + username = authCC.toString(); + } else { + char[] buf = authCC.getBuffer(); + username = new String(buf, 0, colon); + password = new String(buf, colon + 1, authCC.getEnd() - colon - 1); + } + authBC.setOffset(authBC.getOffset() - 6); + credentials = new Credentials(username, password); + } + } + return credentials; + } + + public static class Credentials { + private String username; + private String password; + + public Credentials(String username, String password) { + this.username = username; + this.password = password; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + } + +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/OAuthAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OAuthAuthenticator.java similarity index 51% rename from components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/OAuthAuthenticator.java rename to components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OAuthAuthenticator.java index dc80b6ba91..6fc8177478 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/OAuthAuthenticator.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OAuthAuthenticator.java @@ -16,81 +16,80 @@ * under the License. * */ -package org.wso2.carbon.webapp.authenticator.framework; +package org.wso2.carbon.webapp.authenticator.framework.authenticator; import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.tomcat.util.buf.ByteChunk; +import org.apache.tomcat.util.buf.MessageBytes; import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.core.authenticate.APITokenValidator; import org.wso2.carbon.apimgt.core.gateway.APITokenAuthenticator; -import org.wso2.carbon.apimgt.impl.dao.ApiMgtDAO; import org.wso2.carbon.apimgt.impl.utils.APIUtil; +import org.wso2.carbon.webapp.authenticator.framework.AuthenticationException; +import org.wso2.carbon.webapp.authenticator.framework.AuthenticationFrameworkUtil; +import org.wso2.carbon.webapp.authenticator.framework.Constants; +import org.wso2.carbon.webapp.authenticator.framework.WebappAuthenticator; + +import java.util.StringTokenizer; public class OAuthAuthenticator implements WebappAuthenticator { private static final String OAUTH_AUTHENTICATOR = "OAuthAuthenticator"; private static APITokenAuthenticator authenticator = new APITokenAuthenticator(); - private String bearerToken; private static final Log log = LogFactory.getLog(OAuthAuthenticator.class); - public OAuthAuthenticator(String bearerToken) { - this.bearerToken = bearerToken; - } - @Override public boolean isAuthenticated(Request request) { return false; } @Override - public Status authenticate(Request request) { + public Status authenticate(Request request, Response response) { + StringTokenizer tokenizer = new StringTokenizer(request.getRequestURI(), "/"); + String context = request.getContextPath(); if (context == null || "".equals(context)) { - return Status.CONTINUE; + context = tokenizer.nextToken(); + if (context == null || "".equals(context)) { + return Status.CONTINUE; + } } - boolean contextExist; - Boolean contextValueInCache = null; + boolean isContextCached = false; if (APIUtil.getAPIContextCache().get(context) != null) { - contextValueInCache = Boolean.parseBoolean(APIUtil.getAPIContextCache().get(context).toString()); - } - - if (contextValueInCache != null) { - contextExist = contextValueInCache; - } else { - contextExist = ApiMgtDAO.isContextExist(context); - APIUtil.getAPIContextCache().put(context, contextExist); + isContextCached = Boolean.parseBoolean(APIUtil.getAPIContextCache().get(context).toString()); } - - if (!contextExist) { + if (!isContextCached) { return Status.CONTINUE; } try { - String apiVersion = HandlerUtil.getAPIVersion(request); + String apiVersion = tokenizer.nextToken(); String domain = request.getHeader(APITokenValidator.getAPIManagerClientDomainHeader()); - String authLevel = authenticator.getResourceAuthenticationScheme(context, - apiVersion, - request.getRequestURI(), - request.getMethod()); - if (HandlerConstants.NO_MATCHING_AUTH_SCHEME.equals(authLevel)) { - HandlerUtil.handleNoMatchAuthSchemeCallForRestService(null, - request.getMethod(), request.getRequestURI(), + String authLevel = authenticator.getResourceAuthenticationScheme(context, apiVersion, + request.getRequestURI(), request.getMethod()); + + if (Constants.NO_MATCHING_AUTH_SCHEME.equals(authLevel)) { + AuthenticationFrameworkUtil.handleNoMatchAuthScheme(request, response, request.getMethod(), apiVersion, context); return Status.CONTINUE; } else { + String bearerToken = this.getBearerToken(request); boolean isAuthenticated = - HandlerUtil.doAuthenticate(context, apiVersion, bearerToken, authLevel, domain); + AuthenticationFrameworkUtil.doAuthenticate(context, apiVersion, bearerToken, authLevel, domain); return (isAuthenticated) ? Status.SUCCESS : Status.FAILURE; } } catch (APIManagementException e) { - //ignore - } catch (AuthenticationException e) { log.error("Error occurred while key validation", e); + return Status.FAILURE; + } catch (AuthenticationException e) { + log.error("Failed to authenticate the incoming request", e); + return Status.FAILURE; } - return Status.CONTINUE; } @Override @@ -98,5 +97,19 @@ public class OAuthAuthenticator implements WebappAuthenticator { return OAuthAuthenticator.OAUTH_AUTHENTICATOR; } + private String getBearerToken(Request request) { + MessageBytes authorization = + request.getCoyoteRequest().getMimeHeaders().getValue(Constants.HTTPHeaders.HEADER_HTTP_AUTHORIZATION); + String tokenValue = null; + if (authorization != null) { + authorization.toBytes(); + ByteChunk authBC = authorization.getByteChunk(); + if (authBC.startsWithIgnoreCase("bearer ", 0)) { + String bearerToken = authBC.toString(); + tokenValue = bearerToken.substring(8, bearerToken.length() - 1); + } + } + return tokenValue; + } } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/config/AuthenticatorConfig.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/config/AuthenticatorConfig.java new file mode 100644 index 0000000000..6db4b46b03 --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/config/AuthenticatorConfig.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.wso2.carbon.webapp.authenticator.framework.config; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "Authenticator") +public class AuthenticatorConfig { + + private String name; + private String className; + + @XmlElement(name = "Name", required = true) + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @XmlElement(name = "ClassName", required = true) + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/config/InvalidConfigurationStateException.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/config/InvalidConfigurationStateException.java new file mode 100644 index 0000000000..68d8125eec --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/config/InvalidConfigurationStateException.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.wso2.carbon.webapp.authenticator.framework.config; + +public class InvalidConfigurationStateException extends RuntimeException { + + private static final long serialVersionUID = -3151279311229070297L; + + private String errorMessage; + private int errorCode; + + public InvalidConfigurationStateException(int errorCode, String message) { + super(message); + this.errorCode = errorCode; + } + + public InvalidConfigurationStateException(int errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = errorCode; + } + + public int getErrorCode() { + return errorCode; + } + + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public InvalidConfigurationStateException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public InvalidConfigurationStateException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public InvalidConfigurationStateException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public InvalidConfigurationStateException() { + super(); + } + + public InvalidConfigurationStateException(Throwable cause) { + super(cause); + } + +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/config/WebappAuthenticatorConfig.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/config/WebappAuthenticatorConfig.java new file mode 100644 index 0000000000..007eef108d --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/config/WebappAuthenticatorConfig.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.wso2.carbon.webapp.authenticator.framework.config; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Document; +import org.wso2.carbon.utils.CarbonUtils; +import org.wso2.carbon.webapp.authenticator.framework.AuthenticationFrameworkUtil; +import org.wso2.carbon.webapp.authenticator.framework.AuthenticatorFrameworkException; +import org.xml.sax.SAXException; + +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import java.io.File; +import java.util.List; + +@XmlRootElement(name = "WebappAuthenticatorConfig") +public class WebappAuthenticatorConfig { + + private List authenticators; + private static WebappAuthenticatorConfig config; + + private static final Log log = LogFactory.getLog(WebappAuthenticatorConfig.class); + private static final String AUTHENTICATOR_CONFIG_PATH = + CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "webapp-authenticator-config.xml"; + private static final String AUTHENTICATOR_CONFIG_SCHEMA_PATH = + "resources/config/schema/webapp-authenticator-config-schema.xsd"; + + private WebappAuthenticatorConfig() { + } + + public static WebappAuthenticatorConfig getInstance() { + if (config == null) { + throw new InvalidConfigurationStateException("Webapp Authenticator Configuration is not " + + "initialized properly"); + } + return config; + } + + @XmlElementWrapper(name = "Authenticators", required = true) + @XmlElement(name = "Authenticator", required = true) + public List getAuthenticators() { + return authenticators; + } + + @SuppressWarnings("unused") + public void setAuthenticators(List authenticators) { + this.authenticators = authenticators; + } + + public static void init() throws AuthenticatorFrameworkException { + try { + File authConfig = new File(WebappAuthenticatorConfig.AUTHENTICATOR_CONFIG_PATH); + Document doc = AuthenticationFrameworkUtil.convertToDocument(authConfig); + + /* Un-marshaling Webapp Authenticator configuration */ + JAXBContext ctx = JAXBContext.newInstance(WebappAuthenticatorConfig.class); + Unmarshaller unmarshaller = ctx.createUnmarshaller(); + //unmarshaller.setSchema(getSchema()); + config = (WebappAuthenticatorConfig) unmarshaller.unmarshal(doc); + } catch (JAXBException e) { + throw new AuthenticatorFrameworkException("Error occurred while un-marshalling Webapp Authenticator " + + "Framework Config", e); + } + } + + private static Schema getSchema() throws AuthenticatorFrameworkException { + try { + File deviceManagementSchemaConfig = new File(WebappAuthenticatorConfig.AUTHENTICATOR_CONFIG_SCHEMA_PATH); + SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + return factory.newSchema(deviceManagementSchemaConfig); + } catch (SAXException e) { + throw new AuthenticatorFrameworkException("Error occurred while initializing the schema of " + + "webapp-authenticator-config.xml", e); + } + } + +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkBundleActivator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkBundleActivator.java index 02278eb577..59479ac166 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkBundleActivator.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkBundleActivator.java @@ -25,6 +25,7 @@ import org.osgi.framework.BundleContext; import org.wso2.carbon.tomcat.ext.valves.CarbonTomcatValve; import org.wso2.carbon.tomcat.ext.valves.TomcatValveContainer; import org.wso2.carbon.webapp.authenticator.framework.WebappAuthenticatorFrameworkValve; +import org.wso2.carbon.webapp.authenticator.framework.config.WebappAuthenticatorConfig; import java.util.ArrayList; import java.util.List; @@ -39,6 +40,7 @@ public class WebappAuthenticatorFrameworkBundleActivator implements BundleActiva log.debug("Starting Web Application Authenticator Framework Bundle"); } try { + WebappAuthenticatorConfig.init(); List valves = new ArrayList(); valves.add(new WebappAuthenticatorFrameworkValve()); TomcatValveContainer.addValves(valves); @@ -47,7 +49,7 @@ public class WebappAuthenticatorFrameworkBundleActivator implements BundleActiva log.debug("Web Application Authenticator Framework Bundle has been started successfully"); } } catch (Throwable e) { - log.error("Error occurred while initializing the bundle"); + log.error("Error occurred while initializing the bundle", e); } } diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/user-api-publisher-config.xml b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/user-api-publisher-config.xml index 987ee7513a..12a46052c0 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/user-api-publisher-config.xml +++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/user-api-publisher-config.xml @@ -19,27 +19,27 @@ - appmanager + AppManagerController admin - devices + appmanager 1.0.0 - http://localhost:9763/ + http://localhost:9763/appmanager http,https enrollment admin - enroll + enrollment 1.0.0 - http://localhost:9763/cdm-android-api/enrollment/ + http://localhost:9763/enrollment http,https license admin - license + license-mgt 1.0.0 - http://localhost:9763/cdm-android-api/devices/license + http://localhost:9763/license-mgt http,https @@ -47,7 +47,7 @@ admin operation 1.0.0 - http://localhost:9763/cdm-android-ap/operations/ + http://localhost:9763/operations http,https