forked from community/device-mgt-core
parent
42a8df75e6
commit
a7b447b7db
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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.axiom.om.OMElement;
|
||||
import org.apache.axiom.om.impl.builder.StAXBuilder;
|
||||
import org.apache.axiom.om.util.StAXUtils;
|
||||
import org.apache.axiom.soap.SOAPEnvelope;
|
||||
import org.apache.axiom.soap.SOAPHeader;
|
||||
import org.apache.axiom.soap.SOAPHeaderBlock;
|
||||
import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder;
|
||||
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.coyote.InputBuffer;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.AuthenticationException;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.AuthenticationFrameworkUtil;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.AuthenticationInfo;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.Utils.Utils;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.authenticator.oauth.OAuth2TokenValidator;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.authenticator.oauth.OAuthTokenValidationException;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.authenticator.oauth.OAuthValidationResponse;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.authenticator.oauth.OAuthValidatorFactory;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.*;
|
||||
|
||||
public class BSTAuthenticator implements WebappAuthenticator {
|
||||
|
||||
private Properties properties;
|
||||
private OAuth2TokenValidator tokenValidator;
|
||||
private static final List<String> APPLICABLE_CONTENT_TYPES = new ArrayList<>();
|
||||
private static final Log log = LogFactory.getLog(BSTAuthenticator.class);
|
||||
|
||||
static {
|
||||
APPLICABLE_CONTENT_TYPES.add("application/xml");
|
||||
APPLICABLE_CONTENT_TYPES.add("application/soap+xml");
|
||||
}
|
||||
|
||||
public void init() {
|
||||
if (this.properties == null) {
|
||||
throw new IllegalArgumentException("Required properties needed to initialize OAuthAuthenticator " +
|
||||
"are not provided");
|
||||
}
|
||||
|
||||
String url = this.properties.getProperty("TokenValidationEndpointUrl");
|
||||
if ((url == null) || (url.isEmpty())) {
|
||||
throw new IllegalArgumentException("OAuth token validation endpoint url is not provided");
|
||||
}
|
||||
String adminUsername = this.properties.getProperty("Username");
|
||||
if (adminUsername == null) {
|
||||
throw new IllegalArgumentException("Username to connect to the OAuth token validation endpoint " +
|
||||
"is not provided");
|
||||
}
|
||||
|
||||
String adminPassword = this.properties.getProperty("Password");
|
||||
if (adminPassword == null) {
|
||||
throw new IllegalArgumentException("Password to connect to the OAuth token validation endpoint " +
|
||||
"is not provided");
|
||||
}
|
||||
|
||||
boolean isRemote = Boolean.parseBoolean(this.properties.getProperty("IsRemote"));
|
||||
|
||||
Properties validatorProperties = new Properties();
|
||||
validatorProperties.setProperty("MaxTotalConnections", this.properties.getProperty("MaxTotalConnections"));
|
||||
validatorProperties.setProperty("MaxConnectionsPerHost", this.properties.getProperty("MaxConnectionsPerHost"));
|
||||
this.tokenValidator =
|
||||
OAuthValidatorFactory.getValidator(url, adminUsername, adminPassword, isRemote, validatorProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(Request request) {
|
||||
String contentType = request.getContentType();
|
||||
if (contentType.contains("application/xml") || contentType.contains("application/soap+xml") ||
|
||||
contentType.contains("application/text")) {
|
||||
try {
|
||||
return isBSTHeaderExists(request);
|
||||
} catch (IOException | XMLStreamException e) {
|
||||
log.error("Error occurred while checking if BST authenticator can handle the incoming SOAP message");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationInfo authenticate(Request request, Response response) {
|
||||
String requestUri = request.getRequestURI();
|
||||
String requestMethod = request.getMethod();
|
||||
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
|
||||
if ((requestUri == null) || ("".equals(requestUri))) {
|
||||
authenticationInfo.setStatus(WebappAuthenticator.Status.CONTINUE);
|
||||
return authenticationInfo;
|
||||
}
|
||||
|
||||
StringTokenizer tokenizer = new StringTokenizer(requestUri, "/");
|
||||
String context = tokenizer.nextToken();
|
||||
if ((context == null) || ("".equals(context))) {
|
||||
authenticationInfo.setStatus(WebappAuthenticator.Status.CONTINUE);
|
||||
}
|
||||
String apiVersion = tokenizer.nextToken();
|
||||
|
||||
String authLevel = "any";
|
||||
try {
|
||||
if ("noMatchedAuthScheme".equals(authLevel)) {
|
||||
AuthenticationFrameworkUtil.handleNoMatchAuthScheme(
|
||||
request, response, requestMethod, apiVersion, context);
|
||||
|
||||
authenticationInfo.setStatus(WebappAuthenticator.Status.CONTINUE);
|
||||
} else {
|
||||
String bearerToken = request.getContext().findParameter("BST");
|
||||
|
||||
String resource = requestUri + ":" + requestMethod;
|
||||
|
||||
OAuthValidationResponse oAuthValidationResponse =
|
||||
this.tokenValidator.validateToken(bearerToken, resource);
|
||||
|
||||
if (oAuthValidationResponse.isValid()) {
|
||||
String username = oAuthValidationResponse.getUserName();
|
||||
String tenantDomain = oAuthValidationResponse.getTenantDomain();
|
||||
|
||||
authenticationInfo.setUsername(username);
|
||||
authenticationInfo.setTenantDomain(tenantDomain);
|
||||
authenticationInfo.setTenantId(Utils.getTenantIdOFUser(username + "@" + tenantDomain));
|
||||
if (oAuthValidationResponse.isValid())
|
||||
authenticationInfo.setStatus(WebappAuthenticator.Status.CONTINUE);
|
||||
} else {
|
||||
authenticationInfo.setMessage(oAuthValidationResponse.getErrorMsg());
|
||||
}
|
||||
}
|
||||
} catch (AuthenticationException e) {
|
||||
log.error("Failed to authenticate the incoming request", e);
|
||||
} catch (OAuthTokenValidationException e) {
|
||||
log.error("Failed to authenticate the incoming request due to oauth token validation error.", e);
|
||||
}
|
||||
return authenticationInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "BSTAuthenticator";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(Properties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String name) {
|
||||
return properties.getProperty(name);
|
||||
}
|
||||
|
||||
private static byte[] getUTF8Bytes(String soapEnvelope) {
|
||||
byte[] bytes;
|
||||
try {
|
||||
bytes = soapEnvelope.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.error("Unable to extract bytes in UTF-8 encoding. "
|
||||
+ "Extracting bytes in the system default encoding"
|
||||
+ e.getMessage());
|
||||
bytes = soapEnvelope.getBytes();
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private boolean isBSTHeaderExists(Request request) throws IOException, XMLStreamException {
|
||||
String bstHeader = this.getBSTHeader(request);
|
||||
if (bstHeader == null || bstHeader.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
request.getContext().addParameter("BST", bstHeader);
|
||||
return true;
|
||||
}
|
||||
|
||||
private String getBSTHeader(Request request) throws IOException, XMLStreamException {
|
||||
org.apache.coyote.Request coyoteReq = request.getCoyoteRequest();
|
||||
InputBuffer buf = coyoteReq.getInputBuffer();
|
||||
ByteChunk bc = new ByteChunk();
|
||||
|
||||
buf.doRead(bc, coyoteReq);
|
||||
try (InputStream is = new ByteArrayInputStream(getUTF8Bytes(bc.toString()))) {
|
||||
XMLStreamReader reader = StAXUtils.createXMLStreamReader(is);
|
||||
StAXBuilder builder = new StAXSOAPModelBuilder(reader);
|
||||
SOAPEnvelope envelope = (SOAPEnvelope) builder.getDocumentElement();
|
||||
envelope.build();
|
||||
|
||||
SOAPHeader header = envelope.getHeader();
|
||||
Iterator headerEls = header.getChildrenWithLocalName("Security");
|
||||
if (!headerEls.hasNext()) {
|
||||
return null;
|
||||
}
|
||||
OMElement securityHeader = (OMElement) headerEls.next();
|
||||
Iterator securityHeaderEls = securityHeader.getChildrenWithLocalName("BinarySecurityToken");
|
||||
if (!securityHeaderEls.hasNext()) {
|
||||
return null;
|
||||
}
|
||||
OMElement bstHeader = (OMElement) securityHeaderEls.next();
|
||||
bstHeader.build();
|
||||
return bstHeader.getText();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.test;
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.WebappAuthenticatorRepository;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.authenticator.WebappAuthenticator;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.test.util.MalformedAuthenticator;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.test.util.TestWebappAuthenticator;
|
||||
|
||||
public class WebappAuthenticatorRepositoryTest {
|
||||
|
||||
@Test
|
||||
public void testAddAuthenticator() {
|
||||
WebappAuthenticatorRepository repository = new WebappAuthenticatorRepository();
|
||||
|
||||
WebappAuthenticator addedAuthenticator = new TestWebappAuthenticator();
|
||||
repository.addAuthenticator(addedAuthenticator);
|
||||
|
||||
WebappAuthenticator retriedAuthenticator = repository.getAuthenticator(addedAuthenticator.getName());
|
||||
Assert.assertEquals(addedAuthenticator.getName(), retriedAuthenticator.getName());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
public void testAddMalformedAuthenticator() {
|
||||
WebappAuthenticatorRepository repository = new WebappAuthenticatorRepository();
|
||||
WebappAuthenticator malformedAuthenticator = new MalformedAuthenticator();
|
||||
repository.addAuthenticator(malformedAuthenticator);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
public void testAddAuthenticatorWithNull() {
|
||||
WebappAuthenticatorRepository repository = new WebappAuthenticatorRepository();
|
||||
repository.addAuthenticator(null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
public void testAddAuthenticatorWithEmptyString() {
|
||||
WebappAuthenticatorRepository repository = new WebappAuthenticatorRepository();
|
||||
repository.addAuthenticator(null);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.test.util;
|
||||
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.AuthenticationInfo;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.authenticator.WebappAuthenticator;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
public class MalformedAuthenticator implements WebappAuthenticator {
|
||||
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(Request request) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationInfo authenticate(Request request, Response response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(Properties properties) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.test.util;
|
||||
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.AuthenticationInfo;
|
||||
import org.wso2.carbon.webapp.authenticator.framework.authenticator.WebappAuthenticator;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
public class TestWebappAuthenticator implements WebappAuthenticator {
|
||||
|
||||
private static final String NAME = "TestAuthenticator";
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(Request request) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationInfo authenticate(Request request, Response response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(Properties properties) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in new issue