summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael DÜrre <michael.duerre@highstreet-technologies.com>2021-02-09 08:14:07 +0100
committerKAPIL SINGAL <ks220y@att.com>2021-02-09 20:32:06 +0000
commit934dbb765be113e5eea4da73da90e464d6fa0716 (patch)
tree8be9398bc844321581d624846ef18f4b8581f29a
parent09753774d6faf549928052aeb7eccadc2ab88e0a (diff)
add oauth-provider
new feature for more login security and external logins Issue-ID: CCSDK-3142 Signed-off-by: Michael DÜrre <michael.duerre@highstreet-technologies.com> Change-Id: I6a564a0d1dca44b69bfea2e692fec1f4315cab83 Signed-off-by: Michael DÜrre <michael.duerre@highstreet-technologies.com>
-rw-r--r--sdnr/wt/common/src/main/java/org/onap/ccsdk/features/sdnr/wt/common/http/BaseHTTPClient.java2
-rw-r--r--sdnr/wt/common/src/main/java/org/onap/ccsdk/features/sdnr/wt/common/util/Environment.java5
-rw-r--r--sdnr/wt/featureaggregator/feature-oauth/pom.xml61
-rwxr-xr-xsdnr/wt/featureaggregator/pom.xml1
-rwxr-xr-xsdnr/wt/oauth-provider/pom.xml51
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/pom.xml178
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/OAuth2Realm.java143
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/Config.java238
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/CustomObjectMapper.java39
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakRole.java80
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakUserTokenPayload.java231
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/NoDefinitionFoundException.java33
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthProviderConfig.java135
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthResponseData.java85
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthToken.java52
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlPolicy.java130
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UserTokenPayload.java82
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/AuthHttpServlet.java452
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/HeadersOnlyHttpServletRequest.java469
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappedBaseHttpResponse.java63
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappingBaseHttpClient.java63
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/AuthService.java257
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/KeycloakProviderService.java97
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/NextcloudProviderService.java73
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/OAuthProviderFactory.java44
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/TokenCreator.java106
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestConfig.java36
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestDeserializer.java101
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestProperty.java42
-rw-r--r--sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.config.json18
-rw-r--r--sdnr/wt/oauth-provider/provider-osgi/pom.xml141
-rw-r--r--sdnr/wt/oauth-provider/provider-osgi/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml50
-rw-r--r--sdnr/wt/pom.xml1
33 files changed, 3557 insertions, 2 deletions
diff --git a/sdnr/wt/common/src/main/java/org/onap/ccsdk/features/sdnr/wt/common/http/BaseHTTPClient.java b/sdnr/wt/common/src/main/java/org/onap/ccsdk/features/sdnr/wt/common/http/BaseHTTPClient.java
index 198fb920c..937e2d898 100644
--- a/sdnr/wt/common/src/main/java/org/onap/ccsdk/features/sdnr/wt/common/http/BaseHTTPClient.java
+++ b/sdnr/wt/common/src/main/java/org/onap/ccsdk/features/sdnr/wt/common/http/BaseHTTPClient.java
@@ -71,7 +71,7 @@ public class BaseHTTPClient {
private static final int SSLCERT_PCKS = 0;
private static final int SSLCERT_PEM = 1;
private static final int BUFSIZE = 1024;
- private static final Charset CHARSET = StandardCharsets.UTF_8;
+ public static final Charset CHARSET = StandardCharsets.UTF_8;
private static final String SSLCONTEXT = "TLSv1.2";
private static final int DEFAULT_HTTP_TIMEOUT_MS = 30000; // in ms
diff --git a/sdnr/wt/common/src/main/java/org/onap/ccsdk/features/sdnr/wt/common/util/Environment.java b/sdnr/wt/common/src/main/java/org/onap/ccsdk/features/sdnr/wt/common/util/Environment.java
index 050152f50..89e926654 100644
--- a/sdnr/wt/common/src/main/java/org/onap/ccsdk/features/sdnr/wt/common/util/Environment.java
+++ b/sdnr/wt/common/src/main/java/org/onap/ccsdk/features/sdnr/wt/common/util/Environment.java
@@ -28,6 +28,9 @@ import java.util.Map;
public class Environment {
public static String getVar(String v) {
+ return getVar(v, null);
+ }
+ public static String getVar(String v, String defaultValue) {
if (v.equals("$HOSTNAME")) {
String s = null;
try {
@@ -43,6 +46,6 @@ public class Environment {
if (envName != null && envName.equals(v))
return env.get(envName);
}
- return null;
+ return defaultValue;
}
}
diff --git a/sdnr/wt/featureaggregator/feature-oauth/pom.xml b/sdnr/wt/featureaggregator/feature-oauth/pom.xml
new file mode 100644
index 000000000..e03c6a079
--- /dev/null
+++ b/sdnr/wt/featureaggregator/feature-oauth/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ ONAP : ccsdk features
+ ~ ================================================================================
+ ~ Copyright (C) 2018 highstreet technologies GmbH Intellectual Property.
+ ~ All rights reserved.
+ ~ ================================================================================
+ ~ Update Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ ~ ================================================================================
+ ~ Licensed 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.
+ ~ ============LICENSE_END=======================================================
+ ~
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-feature-aggregator-oauth</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-features :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-oauth-provider</artifactId>
+ <version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-oauth-provider-jar</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/sdnr/wt/featureaggregator/pom.xml b/sdnr/wt/featureaggregator/pom.xml
index 6edd34c19..88df2244a 100755
--- a/sdnr/wt/featureaggregator/pom.xml
+++ b/sdnr/wt/featureaggregator/pom.xml
@@ -44,6 +44,7 @@
<module>feature</module>
<module>feature-devicemanager</module>
<module>feature-devicemanager-base</module>
+ <module>feature-oauth</module>
<module>installer</module>
</modules>
</project>
diff --git a/sdnr/wt/oauth-provider/pom.xml b/sdnr/wt/oauth-provider/pom.xml
new file mode 100755
index 000000000..d8fe6c956
--- /dev/null
+++ b/sdnr/wt/oauth-provider/pom.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ ONAP : ccsdk features
+ ~ ================================================================================
+ ~ Copyright (C) 2018 highstreet technologies GmbH Intellectual Property.
+ ~ All rights reserved.
+ ~ ================================================================================
+ ~ Update Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ ~ ================================================================================
+ ~ Licensed 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.
+ ~ ============LICENSE_END=======================================================
+ ~
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-oauth-provider-top</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-features :: ${project.artifactId}</name>
+
+ <modules>
+ <module>provider-jar</module>
+ <module>provider-osgi</module>
+ </modules>
+
+ <properties>
+ <feature-name>sdnr-wt-oauth-provider</feature-name>
+ </properties>
+</project>
diff --git a/sdnr/wt/oauth-provider/provider-jar/pom.xml b/sdnr/wt/oauth-provider/provider-jar/pom.xml
new file mode 100644
index 000000000..3ee21b2aa
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/pom.xml
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ ONAP : ccsdk features
+ ~ ================================================================================
+ ~ Copyright (C) 2019 highstreet technologies GmbH Intellectual Property.
+ ~ All rights reserved.
+ ~ ================================================================================
+ ~ Update Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ ~ ================================================================================
+ ~ Licensed 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.
+ ~ ============LICENSE_END=======================================================
+ ~
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-oauth-provider-jar</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>ccsdk-features :: ${project.artifactId}</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+
+ <properties>
+ <maven.javadoc.skip>true</maven.javadoc.skip>
+ <checkstyle.skip>true</checkstyle.skip>
+ </properties>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.shiro</groupId>
+ <artifactId>shiro-core</artifactId>
+ <version>1.3.2</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.auth0</groupId>
+ <artifactId>java-jwt</artifactId>
+ <version>3.11.0</version>
+ <exclusions>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>com.highstreet-technologies.aaa</groupId>
+ <artifactId>aaa-shiro</artifactId>
+ <version>0.12.1</version>
+ <exclusions>
+<!-- <exclusion> -->
+<!-- <groupId>org.opendaylight.aaa</groupId> -->
+<!-- <artifactId>aaa-shiro-api</artifactId> -->
+<!-- </exclusion> -->
+ <exclusion>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-cert</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-filterchain</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-password-service-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.opendaylight.aaa.web</groupId>
+ <artifactId>web-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.opendaylight.aaa.web</groupId>
+ <artifactId>servlet-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-text</groupId>
+ <artifactId>commons-text</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>mdsal-binding-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>ehcache-root</groupId>
+ <artifactId>ehcache</artifactId>
+ </exclusion>
+<!-- <exclusion> -->
+<!-- <groupId>org.jolokia</groupId> -->
+<!-- <artifactId>jolokia-osgi</artifactId> -->
+<!-- </exclusion> -->
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>yang-binding</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/OAuth2Realm.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/OAuth2Realm.java
new file mode 100644
index 000000000..a3e4bcc2a
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/OAuth2Realm.java
@@ -0,0 +1,143 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider;
+
+import com.auth0.jwt.interfaces.DecodedJWT;
+import java.io.IOException;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.SimpleAuthenticationInfo;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator;
+import org.opendaylight.aaa.api.shiro.principal.ODLPrincipal;
+import org.opendaylight.aaa.shiro.filters.backport.BearerToken;
+import org.opendaylight.aaa.shiro.realm.TokenAuthRealm;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OAuth2Realm extends TokenAuthRealm {
+
+ public static final String REALM_NAME = "OAuth2Realm";
+ private static final Logger LOG = LoggerFactory.getLogger(OAuth2Realm.class);
+ private final TokenCreator tokenCreator;
+ private final Config config;
+
+ public OAuth2Realm() throws IOException {
+ super();
+ super.setName(REALM_NAME);
+ this.config = Config.getInstance();
+ this.tokenCreator = TokenCreator.getInstance();
+ LOG.info("instantiated");
+
+ }
+
+ @Override
+ public boolean supports(AuthenticationToken token) {
+ boolean supports = (token instanceof BearerToken)
+ || (this.config.doSupportOdlUsers() && (token instanceof UsernamePasswordToken));
+ LOG.debug("supports {} is {}", token == null ? null : token.getClass().getName(), supports);
+ return supports;
+ }
+
+ @Override
+ public String getName() {
+ return REALM_NAME;
+ }
+
+ @Override
+ protected void assertCredentialsMatch(AuthenticationToken atoken, AuthenticationInfo ai)
+ throws AuthenticationException {
+ LOG.debug("assertCredentialsMatch");
+ if (atoken instanceof BearerToken) {
+ if (this.tokenCreator.verify(((BearerToken) atoken).getToken()) == null) {
+ throw new AuthenticationException("Credentials do not match");
+ }
+ } else if (this.config.doSupportOdlUsers() && (atoken instanceof UsernamePasswordToken)) {
+ //nothing to do
+ } else {
+ throw new AuthenticationException("AuthenticationInfo is not an OAuth2AuthenticationInfo");
+ }
+ }
+
+
+ // check what I can do
+ @Override
+ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg) {
+
+ LOG.debug("auth info in shiro");
+ Object principal = arg.getPrimaryPrincipal();
+ if (principal instanceof DecodedJWT) {
+ LOG.debug("detected jwt token");
+ try {
+ DecodedJWT token = (DecodedJWT) arg.getPrimaryPrincipal();
+ String[] roles = token.getClaim("roles").asArray(String.class);
+ SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
+ for (String role : roles) {
+ LOG.trace("found role {} in token", role);
+ authorizationInfo.addRole(role);
+ }
+ return authorizationInfo;
+ } catch (ClassCastException e) {
+ LOG.error("Couldn't decode authorization request", e);
+ }
+ } else if (principal instanceof ODLPrincipal) {
+ LOG.debug("detected basic token");
+ ODLPrincipal odlPrincipal = (ODLPrincipal) principal;
+ return new SimpleAuthorizationInfo(odlPrincipal.getRoles());
+ }
+ return new SimpleAuthorizationInfo();
+ }
+
+
+
+ // check who I am
+ @Override
+ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
+
+ LOG.debug("auth token in shiro:");
+ if (token instanceof UsernamePasswordToken && this.config.doSupportOdlUsers()) {
+ LOG.debug("basic auth token found");
+ return super.doGetAuthenticationInfo(token);
+ } else if (token instanceof BearerToken) {
+ LOG.debug("jwt token found");
+ BearerToken oauthToken = (BearerToken) token;
+
+ DecodedJWT jwt = this.tokenCreator.verify(oauthToken.getToken());
+ if (jwt != null) {
+ SimpleAuthenticationInfo authenticationInfo =
+ new SimpleAuthenticationInfo(jwt, token.getCredentials(), getName());
+ return authenticationInfo;
+
+ }
+ } else {
+ LOG.debug("no valid token found");
+ }
+ throw new AuthenticationException("unable to verify token " + token);
+
+ }
+
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/Config.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/Config.java
new file mode 100644
index 000000000..ba26106c9
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/Config.java
@@ -0,0 +1,238 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.Random;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Config {
+
+ private static final Logger LOG = LoggerFactory.getLogger(Config.class);
+ private static final String DEFAULT_CONFIGFILENAME = "etc/oauth-provider.config.json";
+ private static final String ENVVARIABLE = "${";
+ private static final String REGEXENVVARIABLE = "(\\$\\{[A-Z0-9_-]+\\})";
+ private static final Pattern pattern = Pattern.compile(REGEXENVVARIABLE);
+ private static final String DEFAULT_TOKENISSUER = "Opendaylight";
+ private static final String DEFAULT_TOKENSECRET = generateSecret();
+ private static final String DEFAULT_REDIRECTURI = "/odlux/index.html#/oauth?token=";
+ private static final String DEFAULT_SUPPORTODLUSERS = "true";
+ private static Config _instance;
+
+
+ private List<OAuthProviderConfig> providers;
+ private String host;
+ private String redirectUri;
+ private String supportOdlUsers;
+ private String tokenSecret;
+ private String tokenIssuer;
+
+
+ @Override
+ public String toString() {
+ return "Config [providers=" + providers + ", host=" + host + ", redirectUri=" + redirectUri
+ + ", supportOdlUsers=" + supportOdlUsers + ", tokenSecret=" + tokenSecret + ", tokenIssuer="
+ + tokenIssuer + "]";
+ }
+
+
+
+ public List<OAuthProviderConfig> getProviders() {
+ return providers;
+ }
+
+ public void setProviders(List<OAuthProviderConfig> providers) {
+ this.providers = providers;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public String getRedirectUri() {
+ return redirectUri;
+ }
+
+ public void setRedirectUri(String redirectUri) {
+ this.redirectUri = redirectUri;
+ }
+
+ public String getSupportOdlUsers() {
+ return supportOdlUsers;
+ }
+
+ public void setSupportOdlUsers(String supportOdlUsers) {
+ this.supportOdlUsers = supportOdlUsers;
+ }
+
+ public String getTokenSecret() {
+ return tokenSecret;
+ }
+
+ public void setTokenSecret(String tokenSecret) {
+ this.tokenSecret = tokenSecret;
+ }
+
+ public String getTokenIssuer() {
+ return tokenIssuer;
+ }
+
+ public void setTokenIssuer(String tokenIssuer) {
+ this.tokenIssuer = tokenIssuer;
+ }
+
+ @JsonIgnore
+ private void handleEnvironmentVars() {
+ if (isEnvExpression(tokenIssuer)) {
+ this.tokenIssuer = getProperty(tokenIssuer, null);
+ }
+ if (isEnvExpression(tokenSecret)) {
+ this.tokenSecret = getProperty(tokenSecret, null);
+ }
+ if (isEnvExpression(host)) {
+ this.host = getProperty(host, null);
+ }
+ if (isEnvExpression(redirectUri)) {
+ this.redirectUri = getProperty(redirectUri, null);
+ }
+ if (isEnvExpression(supportOdlUsers)) {
+ this.supportOdlUsers = getProperty(supportOdlUsers, null);
+ }
+ }
+
+ @JsonIgnore
+ private void handleDefaultValues() {
+ if (tokenIssuer == null || tokenIssuer.isEmpty()) {
+ this.tokenIssuer = DEFAULT_TOKENISSUER;
+ }
+ if (tokenSecret == null || tokenSecret.isEmpty()) {
+ this.tokenSecret = DEFAULT_TOKENSECRET;
+ }
+ if (redirectUri == null || redirectUri.isEmpty()) {
+ this.redirectUri = DEFAULT_REDIRECTURI;
+ }
+ if (supportOdlUsers == null || supportOdlUsers.isEmpty()) {
+ this.supportOdlUsers = DEFAULT_SUPPORTODLUSERS;
+ }
+ }
+
+ static boolean isEnvExpression(String key) {
+ return key != null && key.contains(ENVVARIABLE);
+ }
+
+ private static String generateSecret() {
+ int leftLimit = 48; // numeral '0'
+ int rightLimit = 122; // letter 'z'
+ int targetStringLength = 30;
+ Random random = new Random();
+
+ String generatedString = random.ints(leftLimit, rightLimit + 1)
+ .filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97)).limit(targetStringLength)
+ .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
+ return generatedString;
+ }
+
+ /**
+ *
+ * @param key environment var
+ * @param defValue default value if no env var found
+ * @return
+ */
+ public static String getProperty(final String key, final String defValue) {
+ String value = defValue;
+ //try to read env var
+ boolean found = false;
+ if (isEnvExpression(key)) {
+
+ LOG.info("try to find env var(s) for {}", key);
+ final Matcher matcher = pattern.matcher(key);
+ String tmp = new String(key);
+ while (matcher.find() && matcher.groupCount() > 0) {
+ final String mkey = matcher.group(1);
+ if (mkey != null) {
+ try {
+ LOG.info("match found for v={} and env key={}", key, mkey);
+ String envvar = mkey.substring(2, mkey.length() - 1);
+ String env = System.getenv(envvar);
+ tmp = tmp.replace(mkey, env == null ? "" : env);
+ if (env != null && env != "") {
+ found = true;
+ }
+ } catch (SecurityException e) {
+ LOG.warn("unable to read env {}: {}", key, e);
+ }
+ }
+ }
+ if (found) {
+ value = tmp;
+ }
+ }
+ return value;
+ }
+
+ public static boolean getPropertyBoolean(String key, boolean defaultValue) {
+ final String value = getProperty(key, String.valueOf(defaultValue));
+ return value.equals("true");
+ }
+
+ public static Config load(String filename) throws IOException {
+ CustomObjectMapper mapper = new CustomObjectMapper();
+ File file = new File(filename);
+ if (!file.exists()) {
+ throw new FileNotFoundException();
+ }
+ String content = String.join("", Files.readAllLines(file.toPath()));
+ Config cfg = mapper.readValue(content, Config.class);
+ cfg.handleEnvironmentVars();
+ cfg.handleDefaultValues();
+ return cfg;
+ }
+
+
+ @JsonIgnore
+ public boolean doSupportOdlUsers() {
+ return "true".equals(this.supportOdlUsers);
+ }
+
+
+
+ public static Config getInstance() throws IOException {
+ if(_instance==null) {
+ _instance = load(DEFAULT_CONFIGFILENAME);
+ }
+ return _instance;
+ }
+
+
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/CustomObjectMapper.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/CustomObjectMapper.java
new file mode 100644
index 000000000..aa23d4dc1
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/CustomObjectMapper.java
@@ -0,0 +1,39 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data;
+
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class CustomObjectMapper extends ObjectMapper{
+
+ private static final long serialVersionUID = 1L;
+
+
+ public CustomObjectMapper() {
+ this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ this.setSerializationInclusion(Include.NON_NULL);
+ this.enable(MapperFeature.USE_GETTERS_AS_SETTERS);
+ }
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakRole.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakRole.java
new file mode 100644
index 000000000..67186baa7
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakRole.java
@@ -0,0 +1,80 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data;
+
+public class KeycloakRole {
+ private String id;
+ private String name;
+ private String description;
+ private boolean composite;
+ private boolean clientRole;
+ private String containerId; // realmname
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean isClientRole() {
+ return clientRole;
+ }
+
+ public void setClientRole(boolean clientRole) {
+ this.clientRole = clientRole;
+ }
+
+ public String getContainerId() {
+ return containerId;
+ }
+
+ public void setContainerId(String containerId) {
+ this.containerId = containerId;
+ }
+
+ public boolean isComposite() {
+ return composite;
+ }
+
+ public void setComposite(boolean composite) {
+ this.composite = composite;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+} \ No newline at end of file
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakUserTokenPayload.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakUserTokenPayload.java
new file mode 100644
index 000000000..c99ec0d71
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/KeycloakUserTokenPayload.java
@@ -0,0 +1,231 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+
+/**
+ * {
+ "exp": 1610362593,
+ "iat": 1610361393,
+ "jti": "09bd6f2c-5dba-44a0-bd76-cd0d440137d0",
+ "iss": "http://10.20.11.160:8080/auth/realms/onap",
+ "aud": "account",
+ "sub": "446a24bc-d8a0-43dd-afa5-e56eed75deb8",
+ "typ": "Bearer",
+ "azp": "admin-cli",
+ "session_state": "db2c96f4-cc9b-47e8-a83f-a01c50d656f2",
+ "acr": "1",
+ "realm_access": {
+ "roles": [
+ "provision",
+ "offline_access",
+ "uma_authorization"
+ ]
+ },
+ "resource_access": {
+ "account": {
+ "roles": [
+ "manage-account",
+ "manage-account-links",
+ "view-profile"
+ ]
+ }
+ },
+ "scope": "profile email",
+ "email_verified": false,
+ "name": "Luke Skywalker",
+ "preferred_username": "luke.skywalker",
+ "given_name": "Luke",
+ "family_name": "Skywalker",
+ "email": "luke.skywalker@sdnr.onap.org"
+}
+ * @author jack
+ *
+ */
+public class KeycloakUserTokenPayload {
+
+ private long exp;
+ private long iat;
+ private String jti;
+ private String iss;
+ private String aud;
+ private String sub;
+ private String typ;
+ private String azp;
+ @JsonProperty("session_state")
+ private String sessionState;
+ private String acr;
+ @JsonProperty("realm_access")
+ private RealmAccessData realmAccess;
+ @JsonProperty("resource_access")
+ private ResourceAccessData resourceAccess;
+ private String scope;
+ @JsonProperty("email_verified")
+ private String emailVerified;
+ private String name;
+ @JsonProperty("preferred_username")
+ private String preferredUsername;
+ @JsonProperty("given_name")
+ private String givenName;
+ @JsonProperty("family_name")
+ private String familyName;
+ private String email;
+
+ public long getExp() {
+ return exp;
+ }
+ public void setExp(long exp) {
+ this.exp = exp;
+ }
+ public long getIat() {
+ return iat;
+ }
+ public void setIat(long iat) {
+ this.iat = iat;
+ }
+ public String getJti() {
+ return jti;
+ }
+ public void setJti(String jti) {
+ this.jti = jti;
+ }
+ public String getIss() {
+ return iss;
+ }
+ public void setIss(String iss) {
+ this.iss = iss;
+ }
+ public String getAud() {
+ return aud;
+ }
+ public void setAud(String aud) {
+ this.aud = aud;
+ }
+ public String getSub() {
+ return sub;
+ }
+ public void setSub(String sub) {
+ this.sub = sub;
+ }
+ public String getTyp() {
+ return typ;
+ }
+ public void setTyp(String typ) {
+ this.typ = typ;
+ }
+ public String getAzp() {
+ return azp;
+ }
+ public void setAzp(String azp) {
+ this.azp = azp;
+ }
+ public String getSessionState() {
+ return sessionState;
+ }
+ public void setSessionState(String sessionState) {
+ this.sessionState = sessionState;
+ }
+ public String getAcr() {
+ return acr;
+ }
+ public void setAcr(String acr) {
+ this.acr = acr;
+ }
+ public RealmAccessData getRealmAccess() {
+ return realmAccess;
+ }
+ public void setRealmAccess(RealmAccessData realmAccess) {
+ this.realmAccess = realmAccess;
+ }
+ public ResourceAccessData getResourceAccess() {
+ return resourceAccess;
+ }
+ public void setResourceAccess(ResourceAccessData resourceAccess) {
+ this.resourceAccess = resourceAccess;
+ }
+ public String getScope() {
+ return scope;
+ }
+ public void setScope(String scope) {
+ this.scope = scope;
+ }
+ public String getEmailVerified() {
+ return emailVerified;
+ }
+ public void setEmailVerified(String emailVerified) {
+ this.emailVerified = emailVerified;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public String getPreferredUsername() {
+ return preferredUsername;
+ }
+ public void setPreferredUsername(String preferredUsername) {
+ this.preferredUsername = preferredUsername;
+ }
+ public String getGivenName() {
+ return givenName;
+ }
+ public void setGivenName(String givenName) {
+ this.givenName = givenName;
+ }
+ public String getFamilyName() {
+ return familyName;
+ }
+ public void setFamilyName(String familyName) {
+ this.familyName = familyName;
+ }
+ public String getEmail() {
+ return email;
+ }
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+
+ public static class RealmAccessData {
+ private List<String> roles;
+
+ public List<String> getRoles(){
+ return this.roles;
+ }
+ public void setRoles(List<String> roles) {
+ this.roles = roles;
+ }
+ }
+ public static class ResourceAccessData {
+ private RealmAccessData account;
+
+ public RealmAccessData getAccount() {
+ return this.account;
+ }
+ public void setAccount(RealmAccessData account) {
+ this.account = account;
+ }
+ }
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/NoDefinitionFoundException.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/NoDefinitionFoundException.java
new file mode 100644
index 000000000..d13be9602
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/NoDefinitionFoundException.java
@@ -0,0 +1,33 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data;
+
+public class NoDefinitionFoundException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public NoDefinitionFoundException(String message) {
+ super(message);
+ }
+
+
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthProviderConfig.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthProviderConfig.java
new file mode 100644
index 000000000..e4d67432f
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthProviderConfig.java
@@ -0,0 +1,135 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.OAuthProviderFactory.OAuthProvider;
+
+public class OAuthProviderConfig {
+
+ private String host;
+ private String clientId;
+ private String secret;
+ private String id;
+ private String title;
+ private String scope;
+ private OAuthProvider type;
+
+ public OAuthProvider getType() {
+ return type;
+ }
+
+ public OAuthProviderConfig(String id, String host, String clientId, String secret, String scope,
+ String title) {
+ this.id = id;
+ this.host = host;
+ this.clientId = clientId;
+ this.secret = secret;
+ this.scope = scope;
+ this.title = title;
+ }
+
+ @Override
+ public String toString() {
+ return "OAuthProviderConfig [host=" + host + ", clientId=" + clientId + ", secret=" + secret + ", id=" + id
+ + ", title=" + title + ", scope=" + scope + ", type=" + type + "]";
+ }
+
+ public void setType(OAuthProvider type) {
+ this.type = type;
+ }
+
+ public OAuthProviderConfig() {
+ this(null, null, null, null, null, null);
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public void setSecret(String secret) {
+ this.secret = secret;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public void setScope(String scope) {
+ this.scope = scope;
+ }
+
+ public String getId() {
+ return this.id;
+ }
+
+ public String getHost() {
+ return this.host;
+ }
+
+ public String getClientId() {
+ return this.clientId;
+ }
+
+ public String getSecret() {
+ return this.secret;
+ }
+
+ public String getTitle() {
+ return this.title;
+ }
+
+ public String getScope() {
+ return this.scope;
+ }
+
+ @JsonIgnore
+ public void handleEnvironmentVars() {
+ if (Config.isEnvExpression(id)) {
+ this.id = Config.getProperty(id, null);
+ }
+ if (Config.isEnvExpression(host)) {
+ this.host = Config.getProperty(host, null);
+ }
+ if (Config.isEnvExpression(clientId)) {
+ this.clientId = Config.getProperty(clientId, null);
+ }
+ if (Config.isEnvExpression(secret)) {
+ this.secret = Config.getProperty(secret, null);
+ }
+ if (Config.isEnvExpression(scope)) {
+ this.scope = Config.getProperty(scope, null);
+ }
+ if (Config.isEnvExpression(title)) {
+ this.title = Config.getProperty(title, null);
+ }
+ }
+
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthResponseData.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthResponseData.java
new file mode 100644
index 000000000..806a62062
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthResponseData.java
@@ -0,0 +1,85 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data;
+
+public class OAuthResponseData {
+
+ private String access_token;
+ private double expires_in;
+ private double refresh_expires_in;
+ private String refresh_token;
+ private String token_type;
+
+ public OAuthResponseData() {
+ }
+
+ public OAuthResponseData(String token) {
+ this.access_token = token;
+ }
+
+ public String getAccess_token() {
+ return access_token;
+ }
+
+ public String getToken_type() {
+ return token_type;
+ }
+
+ public void setToken_type(String token_type) {
+ this.token_type = token_type;
+ }
+
+ public String getRefresh_token() {
+ return refresh_token;
+ }
+
+ public void setRefresh_token(String refresh_token) {
+ this.refresh_token = refresh_token;
+ }
+
+ public double getRefresh_expires_in() {
+ return refresh_expires_in;
+ }
+
+ public void setRefresh_expires_in(double refresh_expires_in) {
+ this.refresh_expires_in = refresh_expires_in;
+ }
+
+ public double getExpires_in() {
+ return expires_in;
+ }
+
+ public void setExpires_in(double expires_in) {
+ this.expires_in = expires_in;
+ }
+
+ public void setAccess_token(String access_token) {
+ this.access_token = access_token;
+ }
+
+ @Override
+ public String toString() {
+ return "OAuthResponseData [access_token=" + access_token + ", expires_in=" + expires_in
+ + ", refresh_expires_in=" + refresh_expires_in + ", refresh_token=" + refresh_token + ", token_type="
+ + token_type + "]";
+ }
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthToken.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthToken.java
new file mode 100644
index 000000000..1a695f2b0
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OAuthToken.java
@@ -0,0 +1,52 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import org.opendaylight.aaa.shiro.filters.backport.BearerToken;
+
+public class OAuthToken {
+ private final String access_token;
+ private final String token_type;
+ private final long expires_at;
+
+ public OAuthToken(BearerToken btoken) {
+ this.access_token = btoken.getToken();
+ this.token_type = "Bearer";
+ DecodedJWT token = JWT.decode(this.access_token);
+ this.expires_at = token.getExpiresAt().getTime() / 1000L;
+ }
+
+ public String getAccess_token() {
+ return access_token;
+ }
+
+ public String getToken_type() {
+ return token_type;
+ }
+
+ public long getExpires_at() {
+ return expires_at;
+ }
+
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlPolicy.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlPolicy.java
new file mode 100644
index 000000000..28ef3b3b0
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/OdlPolicy.java
@@ -0,0 +1,130 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data;
+
+public class OdlPolicy {
+
+ private String path;
+ private PolicyMethods methods;
+
+
+ public OdlPolicy() {
+
+ }
+
+ public OdlPolicy(String path, PolicyMethods methods) {
+ this.path = path;
+ this.methods = methods;
+ }
+
+ public PolicyMethods getMethods() {
+ return methods;
+ }
+
+ public void setMethods(PolicyMethods methods) {
+ this.methods = methods;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public static OdlPolicy allowAll(String path) {
+ return new OdlPolicy(path, PolicyMethods.allowAll());
+ }
+
+ public static OdlPolicy denyAll(String path) {
+ return new OdlPolicy(path, PolicyMethods.denyAll());
+ }
+
+ public static class PolicyMethods {
+ private boolean get;
+ private boolean post;
+ private boolean put;
+ private boolean delete;
+ private boolean patch;
+
+ public PolicyMethods() {
+
+ }
+
+ public PolicyMethods(boolean get, boolean post, boolean put, boolean del, boolean patch) {
+ this.get = get;
+ this.post = post;
+ this.put = put;
+ this.delete = del;
+ this.patch = patch;
+ }
+
+ public boolean isGet() {
+ return get;
+ }
+
+ public void setGet(boolean get) {
+ this.get = get;
+ }
+
+ public boolean isPost() {
+ return post;
+ }
+
+ public void setPost(boolean post) {
+ this.post = post;
+ }
+
+ public boolean isPut() {
+ return put;
+ }
+
+ public void setPut(boolean put) {
+ this.put = put;
+ }
+
+ public boolean isDelete() {
+ return delete;
+ }
+
+ public void setDelete(boolean delete) {
+ this.delete = delete;
+ }
+
+ public boolean isPatch() {
+ return patch;
+ }
+
+ public void setPatch(boolean patch) {
+ this.patch = patch;
+ }
+
+ public static PolicyMethods allowAll() {
+ return new PolicyMethods(true, true, true, true, true);
+ }
+
+ public static PolicyMethods denyAll() {
+ return new PolicyMethods(false, false, false, false, false);
+ }
+ }
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UserTokenPayload.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UserTokenPayload.java
new file mode 100644
index 000000000..229cdbf78
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/data/UserTokenPayload.java
@@ -0,0 +1,82 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.data;
+
+import java.util.List;
+
+public class UserTokenPayload {
+
+ private List<String> roles;
+ private String preferredUsername;
+ private String givenName;
+ private String familyName;
+ private long exp;
+
+ public long getExp() {
+ return exp;
+ }
+
+ public void setPreferredUsername(String preferredUsername) {
+ this.preferredUsername = preferredUsername;
+ }
+
+ public void setGivenName(String givenName) {
+ this.givenName = givenName;
+ }
+
+ public void setFamilyName(String familyName) {
+ this.familyName = familyName;
+ }
+
+ public void setExp(long exp) {
+ this.exp = exp;
+ }
+
+ public String getPreferredUsername() {
+ return preferredUsername;
+ }
+
+ public String getGivenName() {
+ return givenName;
+ }
+
+ public String getFamilyName() {
+ return familyName;
+ }
+
+ public List<String> getRoles() {
+ return this.roles;
+ }
+
+ public void setRoles(List<String> roles) {
+ this.roles = roles;
+ }
+
+ public static UserTokenPayload create(String username, List<String> roles) {
+ UserTokenPayload data = new UserTokenPayload();
+ data.setPreferredUsername(username);
+ data.setRoles(roles);
+ return data;
+ }
+
+
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/AuthHttpServlet.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/AuthHttpServlet.java
new file mode 100644
index 000000000..f5d344d41
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/AuthHttpServlet.java
@@ -0,0 +1,452 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.http;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.shiro.codec.Base64;
+import org.jolokia.osgi.security.Authenticator;
+import org.onap.ccsdk.features.sdnr.wt.common.http.BaseHTTPClient;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.NoDefinitionFoundException;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthToken;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OdlPolicy;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.AuthService;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.AuthService.PublicOAuthProviderConfig;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.OAuthProviderFactory;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator;
+import org.opendaylight.aaa.api.IDMStoreException;
+import org.opendaylight.aaa.api.IdMService;
+import org.opendaylight.aaa.shiro.filters.backport.BearerToken;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.ShiroConfiguration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.shiro.configuration.Main;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.shiro.configuration.Urls;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AuthHttpServlet extends HttpServlet {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AuthHttpServlet.class.getName());
+ private static final long serialVersionUID = 1L;
+ private static final String BASEURI = "/oauth";
+ private static final String LOGINURI = BASEURI + "/login";
+ //private static final String LOGOUTURI = BASEURI + "/logout";
+ private static final String PROVIDERSURI = BASEURI + "/providers";
+ public static final String REDIRECTURI = BASEURI + "/redirect";
+ private static final String POLICIESURI = BASEURI + "/policies";
+ //private static final String PROVIDERID_REGEX = "^\\" + BASEURI + "\\/providers\\/([^\\/]+)$";
+ private static final String REDIRECTID_REGEX = "^\\" + BASEURI + "\\/redirect\\/([^\\/]+)$";
+ //private static final Pattern PROVIDERID_PATTERN = Pattern.compile(PROVIDERID_REGEX);
+ private static final Pattern REDIRECTID_PATTERN = Pattern.compile(REDIRECTID_REGEX);
+
+ private static final String DEFAULT_DOMAIN = "sdn";
+ private static final String HEAEDER_AUTHORIZATION = "Authorization";
+
+ private static final String CLASSNAME_ODLBASICAUTH =
+ "org.opendaylight.aaa.shiro.filters.ODLHttpAuthenticationFilter";
+ private static final String CLASSNAME_ODLBEARERANDBASICAUTH =
+ "org.opendaylight.aaa.shiro.filters.ODLHttpAuthenticationFilter2";
+ private static final String CLASSNAME_ODLMDSALAUTH =
+ "org.opendaylight.aaa.shiro.realm.MDSALDynamicAuthorizationFilter";
+
+ private final ObjectMapper mapper;
+ /* state <=> AuthProviderService> */
+ private final Map<String, AuthService> providerStore;
+ private Authenticator odlAuthenticator;
+ private IdMService odlIdentityService;
+ private final TokenCreator tokenCreator;
+ private final Config config;
+ private ShiroConfiguration shiroConfiguration;
+
+ public AuthHttpServlet() throws IOException {
+ this.tokenCreator = TokenCreator.getInstance();
+ this.config = Config.getInstance();
+ this.mapper = new ObjectMapper();
+ this.providerStore = new HashMap<>();
+ for (OAuthProviderConfig pc : config.getProviders()) {
+ this.providerStore.put(pc.getId(), OAuthProviderFactory.create(pc.getType(), pc,
+ this.config.getRedirectUri(), TokenCreator.getInstance()));
+ }
+
+ }
+
+ public void setOdlAuthenticator(Authenticator odlAuthenticator) {
+ this.odlAuthenticator = odlAuthenticator;
+ }
+
+ public void setOdlIdentityService(IdMService odlIdentityService) {
+ this.odlIdentityService = odlIdentityService;
+ }
+
+ public void setShiroConfiguration(ShiroConfiguration shiroConfiguration) {
+ this.shiroConfiguration = shiroConfiguration;
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ LOG.debug("GET request for {}", req.getRequestURI());
+ fillHost(req);
+ if (PROVIDERSURI.equals(req.getRequestURI())) {
+ this.sendResponse(resp, HttpServletResponse.SC_OK, getConfigs(this.providerStore.values()));
+ } else if (POLICIESURI.equals(req.getRequestURI())) {
+ this.sendResponse(resp, HttpServletResponse.SC_OK, this.getPoliciesForUser(req));
+ } else if (req.getRequestURI().startsWith(REDIRECTURI)) {
+ this.handleRedirect(req, resp);
+ } else {
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND);
+ }
+
+ }
+
+ /**
+ * find out what urls can be accessed by user and which are forbidden
+ *
+ * urlEntries: "anon" -> any access allowed "authcXXX" -> no grouping rule -> any access for user allowed "authcXXX,
+ * roles[abc] -> user needs to have role abc "authcXXX, roles["abc,def"] -> user needs to have roles abc AND def
+ * "authcXXX, anyroles[abc] -> user needs to have role abc "authcXXX, anyroles["abc,def"] -> user needs to have
+ * roles abc OR def
+ *
+ *
+ * @param req
+ * @return
+ */
+ private List<OdlPolicy> getPoliciesForUser(HttpServletRequest req) {
+ List<Urls> urlRules = this.shiroConfiguration.getUrls();
+ UserTokenPayload data = this.getUserInfo(req);
+ List<OdlPolicy> policies = new ArrayList<>();
+ if (urlRules != null) {
+ LOG.debug("try to find rules for user {} with roles {}",
+ data == null ? "null" : data.getPreferredUsername(), data == null ? "null" : data.getRoles());
+ final String regex = "^([^,]+)[,]?[\\ ]?([anyroles]+)?(\\[\"?([a-zA-Z,]+)\"?\\])?";
+ final Pattern pattern = Pattern.compile(regex);
+ Matcher matcher;
+ for (Urls urlRule : urlRules) {
+ matcher = pattern.matcher(urlRule.getPairValue());
+ if (matcher.find()) {
+ try {
+ final String authClass = getAuthClass(matcher.group(1));
+ Optional<OdlPolicy> policy = Optional.empty();
+ if (authClass.equals(CLASSNAME_ODLBASICAUTH)
+ || authClass.equals(CLASSNAME_ODLBEARERANDBASICAUTH)) {
+ policy = this.getTokenBasedPolicy(urlRule, matcher, data);
+ } else if (authClass.equals(CLASSNAME_ODLMDSALAUTH)) {
+ policy = this.getMdSalBasedPolicy(urlRule, matcher, data);
+ }
+ if (policy.isPresent()) {
+ policies.add(policy.get());
+ } else {
+ LOG.warn("unable to get policy for authClass {} for entry {}", authClass,
+ urlRule.getPairValue());
+ }
+ } catch (NoDefinitionFoundException e) {
+ LOG.warn("unknown authClass: ", e);
+ }
+
+ } else {
+ LOG.warn("unable to detect url role value: {}", urlRule.getPairValue());
+ }
+ }
+ } else {
+ LOG.debug("no url rules found");
+ }
+ return policies;
+ }
+
+ /**
+ * extract policy rule for user from MD-SAL
+ * not yet supported
+ * @param urlRule
+ * @param matcher
+ * @param data
+ * @return
+ */
+ private Optional<OdlPolicy> getMdSalBasedPolicy(Urls urlRule, Matcher matcher, UserTokenPayload data) {
+
+ return Optional.empty();
+ }
+
+ /**
+ * extract policy rule for user from url rules of config
+ * @param urlRule
+ * @param matcher
+ * @param data
+ * @return
+ */
+ private Optional<OdlPolicy> getTokenBasedPolicy(Urls urlRule, Matcher matcher, UserTokenPayload data) {
+ final String url = urlRule.getPairKey();
+ if (!urlRule.getPairValue().contains(",")) {
+ LOG.debug("found rule without roles for '{}'", matcher.group(1));
+ //not important if anon or authcXXX
+ if (data != null || "anon".equals(matcher.group(1))) {
+ return Optional.of(OdlPolicy.allowAll(url));
+ }
+ } else if (data != null) {
+ LOG.debug("found rule with roles '{}'", matcher.group(4));
+ if ("roles".equals(matcher.group(2))) {
+ if (this.rolesMatch(data.getRoles(), Arrays.asList(matcher.group(4).split(",")), false)) {
+ Optional.of(OdlPolicy.allowAll(url));
+ } else {
+ Optional.of(OdlPolicy.denyAll(url));
+ }
+ } else if ("anyroles".equals(matcher.group(2))) {
+ if (this.rolesMatch(data.getRoles(), Arrays.asList(matcher.group(4).split(",")), true)) {
+ Optional.of(OdlPolicy.allowAll(url));
+ } else {
+ Optional.of(OdlPolicy.denyAll(url));
+ }
+ } else {
+ LOG.warn("unable to detect url role value: {}", urlRule.getPairValue());
+ }
+ } else {
+ return Optional.of(OdlPolicy.denyAll(url));
+ }
+ return Optional.empty();
+ }
+
+ private String getAuthClass(String key) throws NoDefinitionFoundException {
+ if ("anon".equals(key)) {
+ return null;
+ }
+ Optional<Main> main =
+ this.shiroConfiguration.getMain().stream().filter((e) -> e.getPairKey().equals(key)).findFirst();
+ if (main.isPresent()) {
+ return main.get().getPairValue();
+ }
+ throw new NoDefinitionFoundException("unable to find def for " + key);
+ }
+
+ private UserTokenPayload getUserInfo(HttpServletRequest req) {
+ if (isBearer(req)) {
+ UserTokenPayload data = TokenCreator.getInstance().decode(req);
+ if (data != null) {
+ return data;
+ }
+ } else if (isBasic(req)) {
+ String username = getBasicAuthUsername(req);
+ if (username != null) {
+ final String domain = getBasicAuthDomain(username);
+ if (!username.contains("@")) {
+ username = String.format("%s@%s", username, domain);
+ }
+ List<String> roles = this.odlIdentityService.listRoles(username, domain);
+ return UserTokenPayload.create(username, roles);
+ }
+ }
+ return null;
+ }
+
+ private static String getBasicAuthDomain(String username) {
+ if (username.contains("@")) {
+ return username.split("@")[1];
+ }
+ return DEFAULT_DOMAIN;
+ }
+
+ private static String getBasicAuthUsername(HttpServletRequest req) {
+ final String header = req.getHeader(HEAEDER_AUTHORIZATION);
+ final String decoded = Base64.decodeToString(header.substring(6));
+ // attempt to decode username/password; otherwise decode as token
+ if (decoded.contains(":")) {
+ return decoded.split(":")[0];
+ }
+ LOG.warn("unable to detect username from basicauth header {}", header);
+ return null;
+ }
+
+ private static boolean isBasic(HttpServletRequest req) {
+ final String header = req.getHeader(HEAEDER_AUTHORIZATION);
+ return header == null ? false : header.startsWith("Basic");
+ }
+
+ private static boolean isBearer(HttpServletRequest req) {
+ final String header = req.getHeader(HEAEDER_AUTHORIZATION);
+ return header == null ? false : header.startsWith("Bearer");
+ }
+
+ private boolean rolesMatch(List<String> userRoles, List<String> policyRoles, boolean any) {
+ if (any) {
+ for (String policyRole : policyRoles) {
+ if (userRoles.contains(policyRole)) {
+ return true;
+ }
+ }
+ return false;
+ } else {
+ for (String policyRole : policyRoles) {
+ if (!userRoles.contains(policyRole)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ }
+
+ private void fillHost(HttpServletRequest req) {
+ String hostUrl = this.config.getHost();
+ if (hostUrl == null) {
+ final String tmp = req.getRequestURL().toString();
+ final String regex = "^(http[s]{0,1}:\\/\\/[^\\/]+)";
+ final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
+ final Matcher matcher = pattern.matcher(tmp);
+ if (matcher.find()) {
+ hostUrl = matcher.group(1);
+ this.config.setHost(hostUrl);
+ }
+ }
+
+ }
+
+ private List<PublicOAuthProviderConfig> getConfigs(Collection<AuthService> values) {
+ List<PublicOAuthProviderConfig> configs = new ArrayList<>();
+ for (AuthService svc : values) {
+ configs.add(svc.getConfig(this.config.getHost()));
+ }
+ return configs;
+ }
+
+ /**
+ * GET /oauth/redirect/{providerID}
+ *
+ * @param req
+ * @param resp
+ * @throws IOException
+ */
+ private void handleRedirect(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ final String uri = req.getRequestURI();
+ final Matcher matcher = REDIRECTID_PATTERN.matcher(uri);
+ if (matcher.find()) {
+ AuthService provider = this.providerStore.getOrDefault(matcher.group(1), null);
+ if (provider != null) {
+ provider.setLocalHostUrl(this.config.getHost());
+ provider.handleRedirect(req, resp);
+ return;
+ }
+ }
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+
+ LOG.debug("POST request for {}", req.getRequestURI());
+ if (this.config.doSupportOdlUsers() && LOGINURI.equals(req.getRequestURI())) {
+ final String username = req.getParameter("username");
+ final String domain = req.getParameter("domain");
+ BearerToken token =
+ this.doLogin(username, req.getParameter("password"), domain != null ? domain : DEFAULT_DOMAIN);
+ if (token != null) {
+ sendResponse(resp, HttpServletResponse.SC_OK, new OAuthToken(token));
+ LOG.debug("login for odluser {} succeeded", username);
+ return;
+ } else {
+ LOG.debug("login failed");
+ }
+
+ }
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND);
+ }
+
+ @Override
+ protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ // final String uri = req.getRequestURI();
+ // final Matcher matcher = PROVIDERID_PATTERN.matcher(uri);
+ // if (matcher.find()) {
+ // final String id = matcher.group(1);
+ // final OAuthProviderConfig config = this.mapper.readValue(req.getInputStream(), OAuthProviderConfig.class);
+ // //this.providerStore.put(id, config);
+ // sendResponse(resp, HttpServletResponse.SC_OK, "");
+ // return;
+ // }
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND);
+ }
+
+ @Override
+ protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ // final String uri = req.getRequestURI();
+ // final Matcher matcher = PROVIDERID_PATTERN.matcher(uri);
+ // if (matcher.find()) {
+ // final String id = matcher.group(1);
+ // this.providerStore.remove(id);
+ // sendResponse(resp, HttpServletResponse.SC_OK, "");
+ // return;
+ // }
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND);
+ }
+
+ private BearerToken doLogin(String username, String password, String domain) {
+ if (!username.contains("@")) {
+ username = String.format("%s@%s", username, domain);
+ }
+ HttpServletRequest req = new HeadersOnlyHttpServletRequest(
+ Map.of("Authorization", BaseHTTPClient.getAuthorizationHeaderValue(username, password)));
+ if (this.odlAuthenticator.authenticate(req)) {
+ try {
+ LOG.info("userids={}", this.odlIdentityService.listUserIDs());
+ LOG.info("domains={}", this.odlIdentityService.listDomains(username));
+ } catch (IDMStoreException e) {
+
+ }
+ List<String> roles = this.odlIdentityService.listRoles(username, domain);
+ UserTokenPayload data = new UserTokenPayload();
+ data.setPreferredUsername(username);
+ data.setFamilyName("");
+ data.setGivenName(username);
+ data.setExp(this.tokenCreator.getDefaultExp());
+ data.setRoles(roles);
+ return this.tokenCreator.createNewJWT(data);
+
+ }
+ return null;
+ }
+
+
+
+ private void sendResponse(HttpServletResponse resp, int code, Object data) throws IOException {
+ byte[] output = data != null ? mapper.writeValueAsString(data).getBytes() : new byte[0];
+ // output
+ resp.setStatus(code);
+ resp.setContentLength(output.length);
+ resp.setContentType("application/json");
+ ServletOutputStream os = null;
+ os = resp.getOutputStream();
+ os.write(output);
+
+ }
+
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/HeadersOnlyHttpServletRequest.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/HeadersOnlyHttpServletRequest.java
new file mode 100644
index 000000000..31b6d696f
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/HeadersOnlyHttpServletRequest.java
@@ -0,0 +1,469 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.http;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.Principal;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpUpgradeHandler;
+import javax.servlet.http.Part;
+
+public class HeadersOnlyHttpServletRequest implements HttpServletRequest{
+
+ private final Map<String,String> headers;
+
+ public HeadersOnlyHttpServletRequest(Map<String,String> headers) {
+ this.headers = headers;
+ }
+ @Override
+ public Object getAttribute(String name) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Enumeration<String> getAttributeNames() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getCharacterEncoding() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public int getContentLength() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public long getContentLengthLong() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getContentType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getParameter(String name) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Enumeration<String> getParameterNames() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String[] getParameterValues(String name) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Map<String, String[]> getParameterMap() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getProtocol() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getScheme() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getServerName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int getServerPort() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getRemoteAddr() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getRemoteHost() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void setAttribute(String name, Object o) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void removeAttribute(String name) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public Locale getLocale() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Enumeration<Locale> getLocales() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean isSecure() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public RequestDispatcher getRequestDispatcher(String path) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getRealPath(String path) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int getRemotePort() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getLocalName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getLocalAddr() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int getLocalPort() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public ServletContext getServletContext() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public AsyncContext startAsync() throws IllegalStateException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse)
+ throws IllegalStateException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean isAsyncStarted() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isAsyncSupported() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public AsyncContext getAsyncContext() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public DispatcherType getDispatcherType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getAuthType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Cookie[] getCookies() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public long getDateHeader(String name) {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getHeader(String name) {
+ return this.headers.getOrDefault(name,null);
+ }
+
+ @Override
+ public Enumeration<String> getHeaders(String name) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Enumeration<String> getHeaderNames() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int getIntHeader(String name) {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getMethod() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getPathInfo() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getPathTranslated() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getContextPath() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getQueryString() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getRemoteUser() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean isUserInRole(String role) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public Principal getUserPrincipal() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getRequestedSessionId() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getRequestURI() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public StringBuffer getRequestURL() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getServletPath() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public HttpSession getSession(boolean create) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public HttpSession getSession() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String changeSessionId() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdValid() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromCookie() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromURL() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromUrl() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public void login(String username, String password) throws ServletException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void logout() throws ServletException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public Collection<Part> getParts() throws IOException, ServletException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Part getPart(String name) throws IOException, ServletException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappedBaseHttpResponse.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappedBaseHttpResponse.java
new file mode 100644
index 000000000..6b1a8eddd
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappedBaseHttpResponse.java
@@ -0,0 +1,63 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.onap.ccsdk.features.sdnr.wt.common.http.BaseHTTPResponse;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.CustomObjectMapper;
+
+public class MappedBaseHttpResponse<T> {
+
+
+ public static final int CODE404 = 404;
+ public static final int CODE200 = 200;
+ public static final MappedBaseHttpResponse<String> UNKNOWN = new MappedBaseHttpResponse<>(-1, null);
+ private static final ObjectMapper mapper = new CustomObjectMapper();
+ public final int code;
+ public final T body;
+
+ public MappedBaseHttpResponse(int code, String body, Class<T> clazz)
+ throws JsonMappingException, JsonProcessingException {
+ this(code, body != null ? mapper.readValue(body, clazz) : null);
+ }
+
+ private MappedBaseHttpResponse(int code, T body) {
+ this.code = code;
+ this.body = body;
+ }
+
+ public MappedBaseHttpResponse(BaseHTTPResponse response, Class<T> clazz)
+ throws JsonMappingException, JsonProcessingException {
+ this(response.code, response.body, clazz);
+ }
+
+ @Override
+ public String toString() {
+ return "BaseHTTPResponse [code=" + code + ", body=" + body + "]";
+ }
+
+ public boolean isSuccess() {
+ return this.code == CODE200;
+ }
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappingBaseHttpClient.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappingBaseHttpClient.java
new file mode 100644
index 000000000..ca455dc72
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/http/client/MappingBaseHttpClient.java
@@ -0,0 +1,63 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Optional;
+import org.onap.ccsdk.features.sdnr.wt.common.http.BaseHTTPClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MappingBaseHttpClient extends BaseHTTPClient {
+
+ private static Logger LOG = LoggerFactory.getLogger(MappingBaseHttpClient.class);
+
+ public MappingBaseHttpClient(String base, boolean trustAllCerts) {
+ super(base, trustAllCerts);
+ }
+
+ public MappingBaseHttpClient(String host) {
+ super(host);
+ }
+
+ public <T> Optional<MappedBaseHttpResponse<String>> sendMappedRequest(String uri, String method, String body,
+ Map<String, String> headers) {
+ return this.sendMappedRequest(uri, method, body != null ? body.getBytes(CHARSET) : null, headers, String.class);
+ }
+
+ public <T> Optional<MappedBaseHttpResponse<T>> sendMappedRequest(String uri, String method, String body,
+ Map<String, String> headers, Class<T> clazz) {
+ return this.sendMappedRequest(uri, method, body != null ? body.getBytes(CHARSET) : null, headers, clazz);
+ }
+
+ protected <T> Optional<MappedBaseHttpResponse<T>> sendMappedRequest(String uri, String method, byte[] body,
+ Map<String, String> headers, Class<T> clazz) {
+ try {
+ return Optional.of(new MappedBaseHttpResponse<T>(this.sendRequest(uri, method, body, headers), clazz));
+ } catch (IOException e) {
+ LOG.warn("problem during request for {}: ", uri, e);
+ }
+ return Optional.empty();
+ }
+
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/AuthService.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/AuthService.java
new file mode 100644
index 000000000..ec685a003
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/AuthService.java
@@ -0,0 +1,257 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.exceptions.JWTDecodeException;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthResponseData;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.AuthHttpServlet;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client.MappedBaseHttpResponse;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client.MappingBaseHttpClient;
+import org.opendaylight.aaa.shiro.filters.backport.BearerToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AuthService {
+
+
+ private static final Logger LOG = LoggerFactory.getLogger(AuthService.class.getName());
+ private final MappingBaseHttpClient httpClient;
+ protected final ObjectMapper mapper;
+ protected final OAuthProviderConfig config;
+ protected final TokenCreator tokenCreator;
+ private final String redirectUri;
+ private String localHostUrl;
+ public void setLocalHostUrl(String url) {
+ this.localHostUrl = url;
+ }
+ protected abstract String getTokenVerifierUri();
+
+ protected abstract Map<String, String> getAdditionalTokenVerifierParams();
+
+ protected abstract ResponseType getResponseType();
+
+ protected abstract boolean doSeperateRolesRequest();
+
+ protected abstract UserTokenPayload mapAccessToken(String spayload)
+ throws JsonMappingException, JsonProcessingException;
+
+ protected abstract String getLoginUrl(String callbackUrl);
+
+ public AuthService(OAuthProviderConfig config, String redirectUri, TokenCreator tokenCreator) {
+ this.config = config;
+ this.tokenCreator = tokenCreator;
+ this.redirectUri = redirectUri;
+ this.mapper = new ObjectMapper();
+ this.mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ this.httpClient = new MappingBaseHttpClient(this.config.getHost());
+ }
+
+ public PublicOAuthProviderConfig getConfig(String host) {
+ return new PublicOAuthProviderConfig(this, host);
+ }
+
+ public void handleRedirect(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ switch (this.getResponseType()) {
+ case CODE:
+ this.handleRedirectCode(req, resp);
+ break;
+ case TOKEN:
+ sendErrorResponse(resp, "not yet implemented");
+ break;
+ case SESSION_STATE:
+ break;
+ }
+
+ }
+
+ private static void sendErrorResponse(HttpServletResponse resp, String message) throws IOException {
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, message);
+
+ }
+
+ private void handleRedirectCode(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ final String code = req.getParameter("code");
+ OAuthResponseData response = this.getTokenForUser(code);
+ if (response != null) {
+ if (this.doSeperateRolesRequest()) {
+
+ } else {
+ this.handleUserInfoToken(response.getAccess_token(), resp);
+ }
+ } else {
+ sendErrorResponse(resp, "unable to verify code");
+ }
+
+ }
+
+ private void handleUserInfoToken(String accessToken, HttpServletResponse resp) throws IOException {
+ try {
+ DecodedJWT jwt = JWT.decode(accessToken);
+
+ String spayload = base64Decode(jwt.getPayload());
+ LOG.debug("payload in jwt from keycload='{}'", spayload);
+
+ UserTokenPayload data = this.mapAccessToken(spayload);
+ BearerToken onapToken = this.tokenCreator.createNewJWT(data);
+ sendTokenResponse(resp, onapToken);
+ } catch (JWTDecodeException | JsonProcessingException e) {
+ LOG.warn("unable to decode jwt token {}: ", accessToken, e);
+ sendErrorResponse(resp, e.getMessage());
+ }
+ }
+
+
+ private void sendTokenResponse(HttpServletResponse resp, BearerToken data) throws IOException {
+ if (this.redirectUri == null) {
+ byte[] output = data != null ? mapper.writeValueAsString(data).getBytes() : new byte[0];
+ resp.setStatus(200);
+ resp.setContentLength(output.length);
+ resp.setContentType("application/json");
+ ServletOutputStream os = null;
+ os = resp.getOutputStream();
+ os.write(output);
+ } else {
+ resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
+ resp.setHeader("Location", assembleUrl(this.localHostUrl, this.redirectUri, data.getToken()));
+ }
+ }
+
+
+
+ private static String base64Decode(String data) {
+ return new String(Base64.getDecoder().decode(data), StandardCharsets.UTF_8);
+ }
+
+ private OAuthResponseData getTokenForUser(String code) {
+
+ Map<String, String> headers = new HashMap<>();
+ headers.put("Content-Type", "application/x-www-form-urlencoded");
+ Map<String, String> params = this.getAdditionalTokenVerifierParams();
+ params.put("code", code);
+ params.put("client_id", this.config.getClientId());
+ params.put("client_secret", this.config.getSecret());
+ params.put("redirect_uri",
+ assembleRedirectUrl(localHostUrl, AuthHttpServlet.REDIRECTURI, this.config.getId()));
+ StringBuilder body = new StringBuilder();
+ for (Entry<String, String> p : params.entrySet()) {
+ body.append(String.format("%s=%s&", p.getKey(), urlEncode(p.getValue())));
+ }
+
+ Optional<MappedBaseHttpResponse<OAuthResponseData>> response = this.httpClient.sendMappedRequest(this.getTokenVerifierUri(),
+ "POST", body.substring(0, body.length() - 1), headers, OAuthResponseData.class);
+ if (response.isPresent() && response.get().isSuccess()) {
+ return response.get().body;
+ }
+ LOG.warn("problem get token for code {}", code);
+
+ return null;
+ }
+
+
+
+ /**
+ * Assemble callback url for service provider {host}{baseUri}/{serviceId} e.g.
+ * http://10.20.0.11:8181/oauth/redirect/keycloak
+ *
+ * @param host
+ * @param baseUri
+ * @param serviceId
+ * @return
+ */
+ public static String assembleRedirectUrl(String host, String baseUri, String serviceId) {
+ return String.format("%s%s/%s", host, baseUri, serviceId);
+ }
+
+ private static String assembleUrl(String host, String uri, String token) {
+ return String.format("%s%s%s", host, uri, token);
+ }
+
+ public static String urlEncode(String s) {
+ return URLEncoder.encode(s, StandardCharsets.UTF_8);
+ }
+
+ public enum ResponseType {
+ CODE, TOKEN, SESSION_STATE
+ }
+
+
+ public static class PublicOAuthProviderConfig {
+
+ private String id;
+ private String title;
+ private String loginUrl;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getLoginUrl() {
+ return loginUrl;
+ }
+
+ public void setLoginUrl(String loginUrl) {
+ this.loginUrl = loginUrl;
+ }
+
+ public PublicOAuthProviderConfig(AuthService authService, String host) {
+ this.id = authService.config.getId();
+ this.title = authService.config.getTitle();
+ this.loginUrl = authService.getLoginUrl(
+ assembleRedirectUrl(host, AuthHttpServlet.REDIRECTURI, this.id));
+ }
+
+ }
+
+
+
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/KeycloakProviderService.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/KeycloakProviderService.java
new file mode 100644
index 000000000..3bfbb3b25
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/KeycloakProviderService.java
@@ -0,0 +1,97 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.KeycloakUserTokenPayload;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload;
+
+public class KeycloakProviderService extends AuthService {
+
+ public static final String ID = "keycloak";
+ private Map<String, String> additionalTokenVerifierParams;
+
+ public KeycloakProviderService(OAuthProviderConfig config, String redirectUri, TokenCreator tokenCreator) {
+ super(config, redirectUri, tokenCreator);
+ this.additionalTokenVerifierParams = new HashMap<>();
+ this.additionalTokenVerifierParams.put("grant_type", "authorization_code");
+ }
+
+ @Override
+ protected String getTokenVerifierUri() {
+ return "/auth/realms/onap/protocol/openid-connect/token";
+ }
+
+ @Override
+ protected String getLoginUrl(String callbackUrl) {
+ return String.format(
+ "%s/auth/realms/onap/protocol/openid-connect/auth?client_id=%s&response_type=code&scope=%s&redirect_uri=%s",
+ this.config.getHost(), urlEncode(this.config.getClientId()), this.config.getScope(),
+ urlEncode(callbackUrl));
+ }
+
+
+
+ private List<String> mapRoles(List<String> data) {
+
+ List<String> filteredRoles =
+ data.stream().filter(role -> !role.equals("uma_authorization") && !role.equals("offline_access"))
+ .map(r -> r).collect(Collectors.toList());
+ return filteredRoles;
+ }
+
+ @Override
+ protected ResponseType getResponseType() {
+ return ResponseType.CODE;
+ }
+
+ @Override
+ protected Map<String, String> getAdditionalTokenVerifierParams() {
+ return this.additionalTokenVerifierParams;
+
+ }
+
+ @Override
+ protected boolean doSeperateRolesRequest() {
+ return false;
+ }
+
+ @Override
+ protected UserTokenPayload mapAccessToken(String spayload) throws JsonMappingException, JsonProcessingException {
+ KeycloakUserTokenPayload payload = mapper.readValue(spayload, KeycloakUserTokenPayload.class);
+ UserTokenPayload data = new UserTokenPayload();
+ data.setExp(payload.getExp() * 1000L);
+ data.setFamilyName(payload.getFamilyName());
+ data.setGivenName(payload.getGivenName());
+ data.setPreferredUsername(payload.getPreferredUsername());
+ data.setRoles(this.mapRoles(payload.getRealmAccess().getRoles()));
+ return data;
+ }
+
+
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/NextcloudProviderService.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/NextcloudProviderService.java
new file mode 100644
index 000000000..ad1da68b3
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/NextcloudProviderService.java
@@ -0,0 +1,73 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import java.util.Map;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload;
+
+public class NextcloudProviderService extends AuthService {
+
+ public NextcloudProviderService(OAuthProviderConfig config, String redirectUri, TokenCreator tokenCreator) {
+ super(config, redirectUri, tokenCreator);
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ protected String getTokenVerifierUri() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected Map<String, String> getAdditionalTokenVerifierParams() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected ResponseType getResponseType() {
+ // TODO Auto-generated method stub
+ return ResponseType.TOKEN;
+ }
+
+ @Override
+ protected boolean doSeperateRolesRequest() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ protected UserTokenPayload mapAccessToken(String spayload) throws JsonMappingException, JsonProcessingException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected String getLoginUrl(String callbackUrl) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+} \ No newline at end of file
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/OAuthProviderFactory.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/OAuthProviderFactory.java
new file mode 100644
index 000000000..a09f150ef
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/OAuthProviderFactory.java
@@ -0,0 +1,44 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers;
+
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthProviderConfig;
+
+public class OAuthProviderFactory {
+
+
+ public static AuthService create(OAuthProvider key, OAuthProviderConfig config, String redirectUri,
+ TokenCreator tokenCreator) {
+ switch (key) {
+ case KEYCLOAK:
+ return new KeycloakProviderService(config, redirectUri, tokenCreator);
+ case NEXTCLOUD:
+ return new NextcloudProviderService(config, redirectUri, tokenCreator);
+ }
+ return null;
+ }
+
+ public static enum OAuthProvider {
+ KEYCLOAK, NEXTCLOUD
+ }
+
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/TokenCreator.java b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/TokenCreator.java
new file mode 100644
index 000000000..3244f90e5
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/main/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/providers/TokenCreator.java
@@ -0,0 +1,106 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTDecodeException;
+import com.auth0.jwt.exceptions.JWTVerificationException;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.auth0.jwt.interfaces.JWTVerifier;
+import java.util.Arrays;
+import java.util.Date;
+import javax.servlet.http.HttpServletRequest;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.UserTokenPayload;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.AuthHttpServlet;
+import org.opendaylight.aaa.shiro.filters.backport.BearerToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TokenCreator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AuthHttpServlet.class.getName());
+ private static final long DEFAULT_TOKEN_LIFETIME_MS = 30 * 60 * 1000;
+ private static final String TOKEN_ISSUER = Config.getProperty("${TOKEN_ISSUER}", "ONAP SDNC");
+ private static TokenCreator _instance;
+ private static final String SECRET = Config.getProperty("${TOKEN_SECRET}", "secret");
+
+ private static final String ROLES_CLAIM = "roles";
+ private static final String FAMILYNAME_CLAIM = "family_name";
+ private static final String NAME_CLAIM = "name";
+
+ public static TokenCreator getInstance() {
+ if (_instance == null) {
+ _instance = new TokenCreator();
+ }
+ return _instance;
+ }
+
+ private TokenCreator() {
+
+ }
+
+ public BearerToken createNewJWT(UserTokenPayload data) {
+ Algorithm algorithm = Algorithm.HMAC256(SECRET);
+ final String token = JWT.create().withIssuer(TOKEN_ISSUER).withExpiresAt(new Date(data.getExp()))
+ .withSubject(data.getPreferredUsername()).withClaim(NAME_CLAIM, data.getGivenName())
+ .withClaim(FAMILYNAME_CLAIM, data.getFamilyName())
+ .withArrayClaim(ROLES_CLAIM, data.getRoles().toArray(new String[data.getRoles().size()]))
+ .sign(algorithm);
+ return new BearerToken(token);
+ }
+
+ public DecodedJWT verify(String token) {
+ DecodedJWT jwt = null;
+ LOG.debug("try to verify token {}", token);
+ try {
+ Algorithm algorithm = Algorithm.HMAC256(SECRET);
+ JWTVerifier verifier = JWT.require(algorithm).withIssuer(TOKEN_ISSUER).build();
+ jwt = verifier.verify(token);
+
+ } catch (JWTVerificationException e) {
+ LOG.warn("unable to verify token {}:", token, e);
+ }
+ return jwt;
+ }
+
+ public long getDefaultExp() {
+ return new Date().getTime() + DEFAULT_TOKEN_LIFETIME_MS;
+ }
+
+ public UserTokenPayload decode(HttpServletRequest req) throws JWTDecodeException {
+ final String authHeader = req.getHeader("Authorization");
+ if (authHeader == null || !authHeader.startsWith("Bearer")) {
+ return null;
+ }
+ DecodedJWT jwt = JWT.decode(authHeader.substring(7));
+ UserTokenPayload data = new UserTokenPayload();
+ data.setRoles(Arrays.asList(jwt.getClaim(ROLES_CLAIM).asArray(String.class)));
+ data.setExp(jwt.getExpiresAt().getTime());
+ data.setFamilyName(jwt.getClaim(FAMILYNAME_CLAIM).asString());
+ data.setGivenName(jwt.getClaim(NAME_CLAIM).asString());
+ data.setPreferredUsername(jwt.getClaim(NAME_CLAIM).asString());
+
+ return data;
+ }
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestConfig.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestConfig.java
new file mode 100644
index 000000000..2b88141ae
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestConfig.java
@@ -0,0 +1,36 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test;
+
+import java.io.IOException;
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config;
+
+public class TestConfig {
+
+ @Test
+ public void test() throws IOException {
+
+ Config config = Config.load("src/test/resources/test.config.json");
+ System.out.println("config="+config);
+ }
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestDeserializer.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestDeserializer.java
new file mode 100644
index 000000000..236c0ffac
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestDeserializer.java
@@ -0,0 +1,101 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.KeycloakUserTokenPayload;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.OAuthResponseData;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client.MappedBaseHttpResponse;
+
+public class TestDeserializer {
+
+ @Test
+ public void test1() throws IOException {
+ final String token = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ1OHNXaTF4QWxjT1pyelY4X0l2VjliMlJTaFdZUWV4aXZYUXNYLTFTME"
+ + "RNIn0.eyJleHAiOjE2MTAzNjE2OTQsImlhdCI6MTYxMDM2MTM5NCwianRpIjoiOWRhOThmMTYtOTEyOS00N2NmLTgzOGQtNWQzYmVkYzYyZTJjIiwiaXNzIjoiaHR0cDovLzEwLjIwLjExLjE2MDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6IjE4MzhjNGYyLTVmZTMtNGYwYy1iMmQyLWQzNjRiMjdhNDk5NyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFkbWluLWNsaSIsInNlc3Npb25fc3RhdGUiOiJjYzcxZmMxZi1hZGQ0LTRhODYtYWU1ZS1jMzRkZjQwM2M3NzIiLCJhY3IiOiIxIiwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiJ9.PUT4NzCM1ej3sNMMCkQa1NuQQwDgn19G-OnWL4NgLvZ3ocJUZ1Yfr9KAPkrJHaiK_HXQqwTA-Ma6Qn7BBMoXNdFjwu0k_HpqyUbBDilGN4wpkGiUeS1p5SW4T_hnWJtwCJ5BYkEvF6WaEbi7MFCbEVO9LVcUvsa-7St1WZ8V8RVfbWgjAu7ejlxe6RYUDMYzIKDj5F5y1-qCyoKzGIjt5ajcA9FWrexHifLJECKO8ZG08Wp7xQld1sYPOdde6XHMwiyNelTwd_EzCBgUw_8664rETGDVtyfuYchowo5Z6fmn4U87L6EGjEuxiAE8f3USy_jh6UF0LnvyTyq_9I"
+ + "M1VA";
+ final String token2 = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ1OHNXaTF4QWxjT1pyelY4X0l2VjliMlJTaFdZUWV4aXZYUXNYLTFTMERNIn0."
+ + "eyJleHAiOjE2MTAzNzA3MDcsImlhdCI6MTYxMDM3MDQwNywianRpIjoiMTczMmI0YzQtNDJlYS00ZWM4LTlhNjMtMTY2YTg4ZTk5ZjQ0IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6IjE4MzhjNGYyLTVmZTMtNGYwYy1iMmQyLWQzNjRiMjdhNDk5NyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFkbWluLWNsaSIsInNlc3Npb25fc3RhdGUiOiJhZjVkYTk2NS1jYmIzLTQzOTYtYmNjNi1kZTBkMDUyOWMyNDgiLCJhY3IiOiIxIiwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiJ9.G_1ByqQlPuJ6_5nuIECfY1VqGufzWQpnFKuOy8YPOOug_jJsIwhVo-JQJiKAxYbHbmDNLrpRJTFlSub0K-1AFyxMw0k_W_YLV0dOTqIakVMTKk9obHFAYtthvhdbt5zb9-33OdCRMMKjA-arj8UeOLEAeFkaeYYBARCD4mEnMFG0vzEiovCCD-jXsfISiS-lOYnCd3hWK8e0brk_bvauxS9W4Z6nptE2564wshe9N_j9-3bQRRAHiAt6f755PhbYgJAu87GdA0bLh_TDe6fie-03goIFMssHoq4n67i-8501UoIG_LccijnfexCS-YwxkfTLbz5d8PvsNadqvFlvig";
+ final String response =
+ "{\"access_token\":\"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ1OHNXaTF4QWxjT1pyelY4X0l2VjliMlJTaFdZUWV4aXZYUXNYLTFTME"
+ + "RNIn0.eyJleHAiOjE2MTAzNjE2OTQsImlhdCI6MTYxMDM2MTM5NCwianRpIjoiOWRhOThmMTYtOTEyOS00N2NmLTgzOGQtNWQzYmVkYzYyZTJjIiwiaXNzIjoiaHR0cDovLzEwLjIwLjExLjE2MDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6IjE4MzhjNGYyLTVmZTMtNGYwYy1iMmQyLWQzNjRiMjdhNDk5NyIsInR5cCI6IkJlYXJlciIsImF6cCI6I"
+ + "mFkbWluLWNsaSIsInNlc3Npb25fc3RhdGUiOiJjYzcxZmMxZi1hZGQ0LTRhODYtYWU1ZS1jMzRkZjQwM2M3NzIiLCJhY3IiOiIxIiwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiJ9.PUT4NzCM1ej3sNMMCkQa1NuQQwDgn19G-OnWL4NgLvZ3ocJUZ1Yfr9KAPkrJHaiK_HX"
+ + "QqwTA-Ma6Qn7BBMoXNdFjwu0k_HpqyUbBDilGN4wpkGiUeS1p5SW4T_hnWJtwCJ5BYkEvF6WaEbi7MFCbEVO9LVcUvsa-7St1WZ8V8RVfbWgjAu7ejlxe6RYUDMYzIKDj5F5y1-qCyoKzGIjt5ajcA9FWrexHifLJECKO8ZG08Wp7xQld1sYPOdde6XHMwiyNelTwd_EzCBgUw_8664rETGDVtyfuYchowo5Z6fmn4U87L6EGjEuxiAE8f3USy_jh6UF0LnvyTyq_9I"
+ + "M1VA\",\"expires_in\":300,\"refresh_expires_in\":1800,\"refresh_token\":\"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1NzdiN2Q3MC00NzMwLTQ0MDMtODk4My04ZjJmYTg4M2U2M2EifQ.eyJleHAiOjE2MTAzNjMxOTQsImlhdCI6MTYxMDM2MTM5NCwianRpIjoiMmNjMGY4YWYtNWY2OC00YmFhLWEyOTctNjMxMjk2YzhmY2"
+ + "U5IiwiaXNzIjoiaHR0cDovLzEwLjIwLjExLjE2MDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsImF1ZCI6Imh0dHA6Ly8xMC4yMC4xMS4xNjA6ODA4MC9hdXRoL3JlYWxtcy9tYXN0ZXIiLCJzdWIiOiIxODM4YzRmMi01ZmUzLTRmMGMtYjJkMi1kMzY0YjI3YTQ5OTciLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoiYWRtaW4tY2xpIiwic2Vzc2lvbl9zdGF0ZSI6I"
+ + "mNjNzFmYzFmLWFkZDQtNGE4Ni1hZTVlLWMzNGRmNDAzYzc3MiIsInNjb3BlIjoiZW1haWwgcHJvZmlsZSJ9.qutqcFuQW-GzaCVNMfiYrbmHYD34GYwBqIbaQbJSY-g\",\"token_type\":\"bearer\",\"not-before-policy\":0,\"session_state\":\"cc71fc1f-add4-4a86-ae5e-c34df403c772\",\"scope\":\"email profile\"} ";
+
+ OAuthResponseData data = new MappedBaseHttpResponse<>(200,response,OAuthResponseData.class).body;
+ assertEquals(token,data.getAccess_token());
+
+ }
+
+ @Test
+ public void testUserPayloadDeser() throws JsonMappingException, JsonProcessingException {
+ final String payload = "{\n"
+ + " \"exp\": 1610362593,\n"
+ + " \"iat\": 1610361393,\n"
+ + " \"jti\": \"09bd6f2c-5dba-44a0-bd76-cd0d440137d0\",\n"
+ + " \"iss\": \"http://10.20.11.160:8080/auth/realms/onap\",\n"
+ + " \"aud\": \"account\",\n"
+ + " \"sub\": \"446a24bc-d8a0-43dd-afa5-e56eed75deb8\",\n"
+ + " \"typ\": \"Bearer\",\n"
+ + " \"azp\": \"admin-cli\",\n"
+ + " \"session_state\": \"db2c96f4-cc9b-47e8-a83f-a01c50d656f2\",\n"
+ + " \"acr\": \"1\",\n"
+ + " \"realm_access\": {\n"
+ + " \"roles\": [\n"
+ + " \"provision\",\n"
+ + " \"offline_access\",\n"
+ + " \"uma_authorization\"\n"
+ + " ]\n"
+ + " },\n"
+ + " \"resource_access\": {\n"
+ + " \"account\": {\n"
+ + " \"roles\": [\n"
+ + " \"manage-account\",\n"
+ + " \"manage-account-links\",\n"
+ + " \"view-profile\"\n"
+ + " ]\n"
+ + " }\n"
+ + " },\n"
+ + " \"scope\": \"profile email\",\n"
+ + " \"email_verified\": false,\n"
+ + " \"name\": \"Luke Skywalker\",\n"
+ + " \"preferred_username\": \"luke.skywalker\",\n"
+ + " \"given_name\": \"Luke\",\n"
+ + " \"family_name\": \"Skywalker\",\n"
+ + " \"email\": \"luke.skywalker@sdnr.onap.org\"\n"
+ + "}";
+
+ ObjectMapper mapper = new ObjectMapper();
+ KeycloakUserTokenPayload data = mapper.readValue(payload,KeycloakUserTokenPayload.class);
+ assertNotNull(data.getRealmAccess());
+ assertEquals(3, data.getRealmAccess().getRoles().size());
+ }
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestProperty.java b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestProperty.java
new file mode 100644
index 000000000..2d03bab1d
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/test/java/org/onap/ccsdk/features/sdnr/wt/oauthprovider/test/TestProperty.java
@@ -0,0 +1,42 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP : ccsdk features
+ * ================================================================================
+ * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ *
+ */
+package org.onap.ccsdk.features.sdnr.wt.oauthprovider.test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config;
+
+public class TestProperty {
+
+ @Ignore
+ @Test
+ public void test() {
+ String hostname = Config.getProperty("${HOSTNAME}", null);
+ System.out.println(hostname);
+ assertNotNull(hostname);
+ hostname = Config.getProperty("${HOSTNAME2}", null);
+ System.out.println(hostname);
+ assertNull(hostname);
+ }
+}
diff --git a/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.config.json b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.config.json
new file mode 100644
index 000000000..88137fdad
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-jar/src/test/resources/test.config.json
@@ -0,0 +1,18 @@
+{
+ "tokenSecret": "${OAUTH_TOKEN_SECRET}",
+ "tokenIssuer": "${OAUTH_TOKEN_ISSUER}",
+ "host": "",
+ "redirectUri": "${OAUTH_ODLUX_REDIRECT_URI}",
+ "supportOdlUsers": "${OAUTH_SUPPORT_ODLUSERS}",
+ "providers": [
+ {
+ "id": "keycloak",
+ "type": "KEYCLOAK",
+ "host": "http://10.20.11.160:8080",
+ "clientId": "odlux.app",
+ "secret": "5da4ea3d-8cc9-4669-bd7e-3ecb91d120cd",
+ "scope": "openid",
+ "title": "OSNL Keycloak Provider"
+ }
+ ]
+} \ No newline at end of file
diff --git a/sdnr/wt/oauth-provider/provider-osgi/pom.xml b/sdnr/wt/oauth-provider/provider-osgi/pom.xml
new file mode 100644
index 000000000..3d17baf96
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-osgi/pom.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ ONAP : ccsdk features
+ ~ ================================================================================
+ ~ Copyright (C) 2019 highstreet technologies GmbH Intellectual Property.
+ ~ All rights reserved.
+ ~ ================================================================================
+ ~ Update Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ ~ ================================================================================
+ ~ Licensed 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.
+ ~ ============LICENSE_END=======================================================
+ ~
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-oauth-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-features :: ${project.artifactId}</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+
+ <properties>
+ <maven.javadoc.skip>true</maven.javadoc.skip>
+ <checkstyle.skip>true</checkstyle.skip>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-oauth-provider-jar</artifactId>
+ <version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-shiro</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.highstreet-technologies.aaa</groupId>
+ <artifactId>aaa-shiro</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.shiro</groupId>
+ <artifactId>shiro-web</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-common</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+ <Bundle-Version>${project.version}</Bundle-Version>
+ <Export-Package>
+ org.onap.ccsdk.features.sdnr.wt.oauthprovider;version=${project.version},
+ org.onap.ccsdk.features.sdnr.wt.oauthprovider.http;version=${project.version},
+ org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.client;version=${project.version},
+ org.onap.ccsdk.features.sdnr.wt.oauthprovider.data;version=${project.version},
+ org.onap.ccsdk.features.sdnr.wt.oauthprovider.services;version=${project.version}
+ </Export-Package>
+ <Import-Package>
+ javax.servlet,
+ javax.servlet.http,
+ javax.net.ssl,
+ javax.crypto,
+ javax.crypto.spec,
+ javax.xml.transform,
+ javax.xml.datatype,
+ javax.management,
+ javax.security.auth,
+ javax.security.auth.login,
+ javax.security.auth.callback,
+ javax.xml.parsers,
+ javax.xml.namespace,
+ javax.xml.transform.stream,
+ org.apache.shiro.authc,
+ org.apache.shiro.authz,
+ org.apache.shiro.realm,
+ org.apache.shiro.subject,
+ org.jolokia.osgi.security,
+ org.onap.ccsdk.features.sdnr.wt.common.http,
+ org.opendaylight.aaa.api,
+ org.opendaylight.aaa.api.shiro.principal,
+ org.opendaylight.aaa.shiro.realm,
+ org.opendaylight.aaa.shiro.filters.backport,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.shiro.configuration,
+ com.fasterxml.jackson.databind,
+ com.fasterxml.jackson.databind.deser.std,
+ com.fasterxml.jackson.databind.ser.std,
+ com.fasterxml.jackson.databind.module,
+ com.fasterxml.jackson.annotation,
+ com.fasterxml.jackson.core.type,
+ com.fasterxml.jackson.core,
+ org.apache.commons.codec.binary
+ </Import-Package>
+ <Embed-Dependency>*;scope=compile|runtime;inline=false</Embed-Dependency>
+ <Embed-Dependency>*;scope=compile|runtime;artifactId=!shiro-core;inline=false</Embed-Dependency>
+ <Embed-Transitive>true</Embed-Transitive>
+ <Fragment-Host>org.apache.shiro.core</Fragment-Host>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/sdnr/wt/oauth-provider/provider-osgi/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml b/sdnr/wt/oauth-provider/provider-osgi/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml
new file mode 100644
index 000000000..f7dd467cd
--- /dev/null
+++ b/sdnr/wt/oauth-provider/provider-osgi/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ ONAP : ccsdk features
+ ~ ================================================================================
+ ~ Copyright (C) 2019 highstreet technologies GmbH Intellectual Property.
+ ~ All rights reserved.
+ ~ ================================================================================
+ ~ Update Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ ~ ================================================================================
+ ~ Licensed 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.
+ ~ ============LICENSE_END=======================================================
+ ~
+ -->
+
+<blueprint xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" odl:use-default-for-reference-types="true">
+
+ <reference id="odlAuthenticator" interface="org.jolokia.osgi.security.Authenticator" />
+
+ <reference id="odlIdentityService" interface="org.opendaylight.aaa.api.IdMService" />
+
+ <odl:clustered-app-config
+ binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.ShiroConfiguration"
+ id="shiroConfiguration" default-config-file-name="aaa-app-config.xml" />
+
+ <bean id="authServlet"
+ class="org.onap.ccsdk.features.sdnr.wt.oauthprovider.http.AuthHttpServlet">
+ <property ref="odlAuthenticator" name="odlAuthenticator" />
+ <property ref="odlIdentityService" name="odlIdentityService" />
+ <property ref="shiroConfiguration" name="shiroConfiguration" />
+ </bean>
+
+ <service interface="javax.servlet.http.HttpServlet" ref="authServlet">
+ <service-properties>
+ <entry key="alias" value="/oauth"/>
+ </service-properties>
+ </service>
+
+</blueprint>
diff --git a/sdnr/wt/pom.xml b/sdnr/wt/pom.xml
index 43a540eef..6b0dfdf6e 100644
--- a/sdnr/wt/pom.xml
+++ b/sdnr/wt/pom.xml
@@ -58,6 +58,7 @@
<module>devicemanager-adapter-manager</module>
<module>mountpoint-registrar</module>
<module>odlux</module>
+ <module>oauth-provider</module>
<module>featureaggregator</module>
</modules>
</project>