Completing JAX-RS authentication framework implementation

revert-70aa11f8
prabathabey 10 years ago
parent 60f50a9242
commit a4485af0c9

@ -46,15 +46,16 @@
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName> <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name> <Bundle-Name>${project.artifactId}</Bundle-Name>
<Bundle-Activator>org.wso2.carbon.webapp.authenticator.framework.internal.WebappAuthenticatorFrameworkBundleActivator</Bundle-Activator> <Bundle-Activator>org.wso2.carbon.webapp.authenticator.framework.internal.WebappAuthenticatorFrameworkBundleActivator</Bundle-Activator>
<Require-Bundle>org.wso2.carbon.tomcat.patch</Require-Bundle> <!--<Require-Bundle>org.wso2.carbon.tomcat.patch</Require-Bundle>-->
<Private-Package> <Private-Package>
org.wso2.carbon.webapp.authenticator.framework.internal org.wso2.carbon.webapp.authenticator.framework.internal
</Private-Package> </Private-Package>
<DynamicImport-Package>*</DynamicImport-Package>
<Export-Package> <Export-Package>
!org.wso2.carbon.webapp.authenticator.framework.internal, !org.wso2.carbon.webapp.authenticator.framework.internal,
org.wso2.carbon.webapp.authenticator.framework.* org.wso2.carbon.webapp.authenticator.framework.*
</Export-Package> </Export-Package>
<Fragment-Host>tomcat</Fragment-Host> <!--<Fragment-Host>tomcat</Fragment-Host>-->
</instructions> </instructions>
</configuration> </configuration>
</plugin> </plugin>

@ -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);
}
}
}

@ -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);
}
}

@ -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;
}
}

@ -17,11 +17,27 @@
*/ */
package org.wso2.carbon.webapp.authenticator.framework; package org.wso2.carbon.webapp.authenticator.framework;
public class HandlerConstants { public final class Constants {
public static final String HEADER_AUTHORIZATION = "Authorization";
public static final String TOKEN_NAME_BEARER = "Bearer";
public static final String AUTHORIZATION_HEADER_PREFIX_BEARER = "Bearer";
public static final String NO_MATCHING_AUTH_SCHEME = "noMatchedAuthScheme"; 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";
}
} }

@ -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;
}
}

@ -19,6 +19,7 @@
package org.wso2.carbon.webapp.authenticator.framework; package org.wso2.carbon.webapp.authenticator.framework;
import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
public interface WebappAuthenticator { public interface WebappAuthenticator {
@ -28,7 +29,7 @@ public interface WebappAuthenticator {
boolean isAuthenticated(Request request); boolean isAuthenticated(Request request);
Status authenticate(Request request); Status authenticate(Request request, Response response);
String getAuthenticatorName(); String getAuthenticatorName();

@ -23,45 +23,13 @@ import org.apache.catalina.util.Base64;
import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.CharChunk; import org.apache.tomcat.util.buf.CharChunk;
import org.apache.tomcat.util.buf.MessageBytes; 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 class WebappAuthenticatorFactory {
public static WebappAuthenticator getAuthenticator(Request request) { public static WebappAuthenticator getAuthenticator(Request request) {
MessageBytes authorization = request.getCoyoteRequest().getMimeHeaders().getValue("authorization"); return new OAuthAuthenticator();
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");
} }
} }

@ -18,29 +18,37 @@
*/ */
package org.wso2.carbon.webapp.authenticator.framework; package org.wso2.carbon.webapp.authenticator.framework;
import org.apache.axis2.context.MessageContext;
import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response; import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase; import org.apache.commons.logging.Log;
import org.wso2.carbon.core.services.authentication.CarbonServerAuthenticator; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.tomcat.ext.valves.CarbonTomcatValve; import org.wso2.carbon.tomcat.ext.valves.CarbonTomcatValve;
import org.wso2.carbon.tomcat.ext.valves.CompositeValve; import org.wso2.carbon.tomcat.ext.valves.CompositeValve;
import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class WebappAuthenticatorFrameworkValve extends CarbonTomcatValve { public class WebappAuthenticatorFrameworkValve extends CarbonTomcatValve {
private static final Log log = LogFactory.getLog(WebappAuthenticatorFrameworkValve.class);
@Override @Override
public void invoke(Request request, Response response, CompositeValve compositeValve) { public void invoke(Request request, Response response, CompositeValve compositeValve) {
WebappAuthenticator authenticator = WebappAuthenticatorFactory.getAuthenticator(request); 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) { switch (status) {
case SUCCESS: case SUCCESS:
case CONTINUE: case CONTINUE:
getNext().invoke(request, response, compositeValve); this.getNext().invoke(request, response, compositeValve);
case FAILURE: case FAILURE:
//do something AuthenticationFrameworkUtil.handleResponse(request, response, HttpServletResponse.SC_UNAUTHORIZED,
"Failed to authorize the incoming request");
} }
} }
} }

@ -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;
}
}
}

@ -16,81 +16,80 @@
* under the License. * 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.Request;
import org.apache.catalina.connector.Response;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; 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.api.APIManagementException;
import org.wso2.carbon.apimgt.core.authenticate.APITokenValidator; import org.wso2.carbon.apimgt.core.authenticate.APITokenValidator;
import org.wso2.carbon.apimgt.core.gateway.APITokenAuthenticator; 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.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 { public class OAuthAuthenticator implements WebappAuthenticator {
private static final String OAUTH_AUTHENTICATOR = "OAuthAuthenticator"; private static final String OAUTH_AUTHENTICATOR = "OAuthAuthenticator";
private static APITokenAuthenticator authenticator = new APITokenAuthenticator(); private static APITokenAuthenticator authenticator = new APITokenAuthenticator();
private String bearerToken;
private static final Log log = LogFactory.getLog(OAuthAuthenticator.class); private static final Log log = LogFactory.getLog(OAuthAuthenticator.class);
public OAuthAuthenticator(String bearerToken) {
this.bearerToken = bearerToken;
}
@Override @Override
public boolean isAuthenticated(Request request) { public boolean isAuthenticated(Request request) {
return false; return false;
} }
@Override @Override
public Status authenticate(Request request) { public Status authenticate(Request request, Response response) {
StringTokenizer tokenizer = new StringTokenizer(request.getRequestURI(), "/");
String context = request.getContextPath(); String context = request.getContextPath();
if (context == null || "".equals(context)) { if (context == null || "".equals(context)) {
return Status.CONTINUE; context = tokenizer.nextToken();
if (context == null || "".equals(context)) {
return Status.CONTINUE;
}
} }
boolean contextExist; boolean isContextCached = false;
Boolean contextValueInCache = null;
if (APIUtil.getAPIContextCache().get(context) != null) { if (APIUtil.getAPIContextCache().get(context) != null) {
contextValueInCache = Boolean.parseBoolean(APIUtil.getAPIContextCache().get(context).toString()); isContextCached = Boolean.parseBoolean(APIUtil.getAPIContextCache().get(context).toString());
}
if (contextValueInCache != null) {
contextExist = contextValueInCache;
} else {
contextExist = ApiMgtDAO.isContextExist(context);
APIUtil.getAPIContextCache().put(context, contextExist);
} }
if (!isContextCached) {
if (!contextExist) {
return Status.CONTINUE; return Status.CONTINUE;
} }
try { try {
String apiVersion = HandlerUtil.getAPIVersion(request); String apiVersion = tokenizer.nextToken();
String domain = request.getHeader(APITokenValidator.getAPIManagerClientDomainHeader()); String domain = request.getHeader(APITokenValidator.getAPIManagerClientDomainHeader());
String authLevel = authenticator.getResourceAuthenticationScheme(context, String authLevel = authenticator.getResourceAuthenticationScheme(context, apiVersion,
apiVersion, request.getRequestURI(), request.getMethod());
request.getRequestURI(),
request.getMethod()); if (Constants.NO_MATCHING_AUTH_SCHEME.equals(authLevel)) {
if (HandlerConstants.NO_MATCHING_AUTH_SCHEME.equals(authLevel)) { AuthenticationFrameworkUtil.handleNoMatchAuthScheme(request, response, request.getMethod(),
HandlerUtil.handleNoMatchAuthSchemeCallForRestService(null,
request.getMethod(), request.getRequestURI(),
apiVersion, context); apiVersion, context);
return Status.CONTINUE; return Status.CONTINUE;
} else { } else {
String bearerToken = this.getBearerToken(request);
boolean isAuthenticated = boolean isAuthenticated =
HandlerUtil.doAuthenticate(context, apiVersion, bearerToken, authLevel, domain); AuthenticationFrameworkUtil.doAuthenticate(context, apiVersion, bearerToken, authLevel, domain);
return (isAuthenticated) ? Status.SUCCESS : Status.FAILURE; return (isAuthenticated) ? Status.SUCCESS : Status.FAILURE;
} }
} catch (APIManagementException e) { } catch (APIManagementException e) {
//ignore
} catch (AuthenticationException e) {
log.error("Error occurred while key validation", 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 @Override
@ -98,5 +97,19 @@ public class OAuthAuthenticator implements WebappAuthenticator {
return OAuthAuthenticator.OAUTH_AUTHENTICATOR; 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;
}
} }

@ -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;
}
}

@ -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);
}
}

@ -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<AuthenticatorConfig> 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<AuthenticatorConfig> getAuthenticators() {
return authenticators;
}
@SuppressWarnings("unused")
public void setAuthenticators(List<AuthenticatorConfig> 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);
}
}
}

@ -25,6 +25,7 @@ import org.osgi.framework.BundleContext;
import org.wso2.carbon.tomcat.ext.valves.CarbonTomcatValve; import org.wso2.carbon.tomcat.ext.valves.CarbonTomcatValve;
import org.wso2.carbon.tomcat.ext.valves.TomcatValveContainer; import org.wso2.carbon.tomcat.ext.valves.TomcatValveContainer;
import org.wso2.carbon.webapp.authenticator.framework.WebappAuthenticatorFrameworkValve; import org.wso2.carbon.webapp.authenticator.framework.WebappAuthenticatorFrameworkValve;
import org.wso2.carbon.webapp.authenticator.framework.config.WebappAuthenticatorConfig;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -39,6 +40,7 @@ public class WebappAuthenticatorFrameworkBundleActivator implements BundleActiva
log.debug("Starting Web Application Authenticator Framework Bundle"); log.debug("Starting Web Application Authenticator Framework Bundle");
} }
try { try {
WebappAuthenticatorConfig.init();
List<CarbonTomcatValve> valves = new ArrayList<CarbonTomcatValve>(); List<CarbonTomcatValve> valves = new ArrayList<CarbonTomcatValve>();
valves.add(new WebappAuthenticatorFrameworkValve()); valves.add(new WebappAuthenticatorFrameworkValve());
TomcatValveContainer.addValves(valves); TomcatValveContainer.addValves(valves);
@ -47,7 +49,7 @@ public class WebappAuthenticatorFrameworkBundleActivator implements BundleActiva
log.debug("Web Application Authenticator Framework Bundle has been started successfully"); log.debug("Web Application Authenticator Framework Bundle has been started successfully");
} }
} catch (Throwable e) { } catch (Throwable e) {
log.error("Error occurred while initializing the bundle"); log.error("Error occurred while initializing the bundle", e);
} }
} }

@ -19,27 +19,27 @@
<APIPublisherConfig> <APIPublisherConfig>
<APIs> <APIs>
<API> <API>
<Name>appmanager</Name> <Name>AppManagerController</Name>
<Owner>admin</Owner> <Owner>admin</Owner>
<Context>devices</Context> <Context>appmanager</Context>
<Version>1.0.0</Version> <Version>1.0.0</Version>
<Endpoint>http://localhost:9763/</Endpoint> <Endpoint>http://localhost:9763/appmanager</Endpoint>
<Transports>http,https</Transports> <Transports>http,https</Transports>
</API> </API>
<API> <API>
<Name>enrollment</Name> <Name>enrollment</Name>
<Owner>admin</Owner> <Owner>admin</Owner>
<Context>enroll</Context> <Context>enrollment</Context>
<Version>1.0.0</Version> <Version>1.0.0</Version>
<Endpoint>http://localhost:9763/cdm-android-api/enrollment/</Endpoint> <Endpoint>http://localhost:9763/enrollment</Endpoint>
<Transports>http,https</Transports> <Transports>http,https</Transports>
</API> </API>
<API> <API>
<Name>license</Name> <Name>license</Name>
<Owner>admin</Owner> <Owner>admin</Owner>
<Context>license</Context> <Context>license-mgt</Context>
<Version>1.0.0</Version> <Version>1.0.0</Version>
<Endpoint>http://localhost:9763/cdm-android-api/devices/license</Endpoint> <Endpoint>http://localhost:9763/license-mgt</Endpoint>
<Transports>http,https</Transports> <Transports>http,https</Transports>
</API> </API>
<API> <API>
@ -47,7 +47,7 @@
<Owner>admin</Owner> <Owner>admin</Owner>
<Context>operation</Context> <Context>operation</Context>
<Version>1.0.0</Version> <Version>1.0.0</Version>
<Endpoint>http://localhost:9763/cdm-android-ap/operations/</Endpoint> <Endpoint>http://localhost:9763/operations</Endpoint>
<Transports>http,https</Transports> <Transports>http,https</Transports>
</API> </API>
</APIs> </APIs>

Loading…
Cancel
Save