diff --git a/Jenkinsfile b/Jenkinsfile
index 6415a6761..42c0991eb 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -27,11 +27,11 @@ node {
stage('Push image') {
- docker.withRegistry('', 'dockerhub') {
+ docker.withRegistry('ghcr.io', 'sunbird-rc') {
app.push("${env.BUILD_NUMBER}")
app.push("latest")
}
- docker.withRegistry('', 'dockerhub') {
+ docker.withRegistry('ghrc.io', 'sunbird-rc') {
claimApp.push("${env.BUILD_NUMBER}")
claimApp.push("latest")
}
diff --git a/Makefile b/Makefile
index 8dc3572ed..fc4c3934f 100644
--- a/Makefile
+++ b/Makefile
@@ -51,6 +51,19 @@ test: build
@cd java/apitest && MODE=async ../mvnw -Pe2e test
@docker-compose down
@rm -rf db-data-2 || echo "no permission to delete"
+ # test with fusionauth
+ @docker-compose --env-file test_environments/test_with_fusionauth.env -f docker-compose.yml -f services/sample-fusionauth-service/docker-compose.yml up -d db es fusionauth fusionauthwrapper
+ sleep 20
+ @echo "Starting the test" && sh build/wait_for_port.sh 9011
+ @echo "Starting the test" && sh build/wait_for_port.sh 3990
+ sleep 20
+ @docker-compose --env-file test_environments/test_with_fusionauth.env -f docker-compose.yml -f services/sample-fusionauth-service/docker-compose.yml up -d --no-deps registry
+ @echo "Starting the test" && sh build/wait_for_port.sh 8081
+ @docker-compose -f docker-compose.yml -f services/sample-fusionauth-service/docker-compose.yml ps
+ @curl -v http://localhost:8081/health
+ @cd java/apitest && MODE=fusionauth ../mvnw -Pe2e test || echo 'Tests failed'
+ @docker-compose -f docker-compose.yml -f services/sample-fusionauth-service/docker-compose.yml down
+ @rm -rf db-data-3 || echo "no permission to delete"
make -C services/certificate-signer test
make -C services/public-key-service test
make -C services/context-proxy-service test
diff --git a/docker-compose.yml b/docker-compose.yml
index fd1b7ec01..5e763f0df 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -59,7 +59,10 @@ services:
- elastic_search_password=${ELASTIC_SEARCH_PASSWORD}
- search_providerName=${SEARCH_PROVIDER_NAME-dev.sunbirdrc.registry.service.NativeSearchService}
- sunbird_sso_realm=${KEYCLOAK_REALM-sunbird-rc}
- - sunbird_sso_url=http://keycloak:8080/auth
+ - sunbird_sso_url=${sunbird_sso_url-http://keycloak:8080/auth}
+ - oauth2_resource_uri=${oauth2_resource_uri-http://keycloak:8080/auth/realms/sunbird-rc}
+ - oauth2_resource_roles_path=${oauth2_resource_roles_path-realm_access.roles}
+ - identity_provider=${identity_provider-dev.sunbirdrc.auth.keycloak.KeycloakProviderImpl}
- sunbird_sso_admin_client_id=${KEYCLOAK_ADMIN_CLIENT_ID-admin-api}
- sunbird_sso_client_id=${KEYCLOAK_CLIENT_ID-registry-frontend}
- sunbird_sso_admin_client_secret=${KEYCLOAK_SECRET}
@@ -99,6 +102,8 @@ services:
depends_on:
db:
condition: service_healthy
+ keycloak:
+ condition: service_healthy
healthcheck:
test:
[
diff --git a/java/apitest/src/test/java/e2e/registry/StudentWithPasswordRequest.json b/java/apitest/src/test/java/e2e/registry/StudentWithPasswordRequest.json
index a41374e92..2af9e514f 100644
--- a/java/apitest/src/test/java/e2e/registry/StudentWithPasswordRequest.json
+++ b/java/apitest/src/test/java/e2e/registry/StudentWithPasswordRequest.json
@@ -1,9 +1,9 @@
{
"userDetails": {
- "passkey": "abcd"
+ "passkey": "abcd@12345"
},
"contactDetails": {
"mobile": "9876543210",
"email": "abcd@gmail.com"
}
-}
\ No newline at end of file
+}
diff --git a/java/apitest/src/test/java/e2e/registry/certificate.feature b/java/apitest/src/test/java/e2e/registry/certificate.feature
index f1c86b755..4795fe69f 100644
--- a/java/apitest/src/test/java/e2e/registry/certificate.feature
+++ b/java/apitest/src/test/java/e2e/registry/certificate.feature
@@ -2,6 +2,8 @@ Feature: Get certificate pdf
Background:
* def certUrl = "http://localhost:8078"
* def templateBody = {"certificate": "{\"name\":\"Test Name\", \"dob\":\"2002-12-22\"}","templateUrl": "http://registry:8081/api/v1/templates/Student.html"}
+
+ @envnot=fusionauth
Scenario:
And header Accept = 'application/pdf'
Given url certUrl
@@ -11,6 +13,7 @@ Feature: Get certificate pdf
Then status 200
#* print response
+ @envnot=fusionauth
Scenario:
And header Accept = 'application/pdf'
Given url certUrl
diff --git a/java/apitest/src/test/java/e2e/registry/fusionauth-registry.feature b/java/apitest/src/test/java/e2e/registry/fusionauth-registry.feature
new file mode 100644
index 000000000..1bea1f399
--- /dev/null
+++ b/java/apitest/src/test/java/e2e/registry/fusionauth-registry.feature
@@ -0,0 +1,60 @@
+Feature: Registry api tests
+ Background:
+ * string registryUrl = "http://localhost:8081"
+ * string authUrl = "http://localhost:9011"
+ * url registryUrl
+ * def admin_token = ""
+ * def client_secret = 'a52c5f4a-89fd-40b9-aea2-3f711f14c889'
+ * def sleep = function(millis){ java.lang.Thread.sleep(millis) }
+ @env=fusionauth
+ Scenario: Create student with password schema and verify if password is set
+ # get admin token
+ * url authUrl
+ * path '/oauth2/token'
+ * header Content-Type = 'application/x-www-form-urlencoded; charset=utf-8'
+ * header Host = 'fusionauth:9011'
+ * form field grant_type = 'password'
+ * form field client_id = '85a03867-dccf-4882-adde-1a79aeec50df'
+ * form field username = 'admin@sunbirdrc.dev'
+ * form field password = 'admin@12345'
+ * method post
+ Then status 200
+ And print response.access_token
+ * def admin_token = 'Bearer ' + response.access_token
+ # create student schema
+ Given url registryUrl
+ And path 'api/v1/Schema'
+ And header Authorization = admin_token
+ And request read('StudentWithPasswordSchemaRequest.json')
+ When method post
+ Then status 200
+ And response.params.status == "SUCCESSFUL"
+ # invite entity for student
+ Given url registryUrl
+ And path 'api/v1/StudentWithPassword/invite'
+ * def studentRequest = read('StudentWithPasswordRequest.json')
+ And request studentRequest
+ When method post
+ Then status 200
+ * def studentOsid = response.result.StudentWithPassword.osid
+ # get student token
+ * url authUrl
+ * path '/oauth2/token'
+ * header Content-Type = 'application/x-www-form-urlencoded; charset=utf-8'
+ * header Host = 'fusionauth:9011'
+ * form field grant_type = 'password'
+ * form field client_id = '85a03867-dccf-4882-adde-1a79aeec50df'
+ * form field username = studentRequest.contactDetails.mobile
+ * form field password = studentRequest.userDetails.passkey
+ * method post
+ Then status 200
+ And print response.access_token
+ * def student_token = 'Bearer ' + response.access_token
+ * sleep(3000)
+ # get student info
+ Given url registryUrl
+ And path 'api/v1/StudentWithPassword/'
+ And header Authorization = student_token
+ When method get
+ Then status 200
+ And response[0].osid.length > 0
diff --git a/java/apitest/src/test/java/e2e/registry/registry.feature b/java/apitest/src/test/java/e2e/registry/registry.feature
index 8031a5721..90f96af73 100644
--- a/java/apitest/src/test/java/e2e/registry/registry.feature
+++ b/java/apitest/src/test/java/e2e/registry/registry.feature
@@ -9,12 +9,12 @@ Feature: Registry api tests
* def admin_token = ""
* def client_secret = 'a52c5f4a-89fd-40b9-aea2-3f711f14c889'
* def sleep = function(millis){ java.lang.Thread.sleep(millis) }
-
+ @envnot=fusionauth
Scenario: health check
Given path 'health'
When method get
Then status 200
-
+ @envnot=fusionauth
Scenario: Create birth certificate schema and issue credentials
# get admin token
* url authUrl
@@ -102,7 +102,7 @@ Feature: Registry api tests
And response.params.status == "UNSUCCESSFUL"
And response.params.errmsg == "entity status is inactive"
-
+ @envnot=fusionauth
Scenario: Create student schema and verify crud apis
# get admin token
* url authUrl
@@ -234,6 +234,7 @@ Feature: Registry api tests
And response.length == 1
And response[0].contact == '#notpresent'
+ @envnot=fusionauth
Scenario: Create Board and invite institutes
# get admin token
* url authUrl
@@ -347,6 +348,7 @@ Feature: Registry api tests
And assert response[0].address[0].phoneNo.length == 1
And assert response[0].address[0].phoneNo[0] == "444"
+ @envnot=fusionauth
Scenario: write a api test, to test the schema not found error
# get admin token
* url authUrl
@@ -486,6 +488,7 @@ Feature: Registry api tests
And response.params.status =="UNSUCCESSFUL"
And response.params.errmsg == "Schema 'Teacher1' not found"
+ @envnot=fusionauth
Scenario: Create student with password schema and verify if password is set
# get admin token
* url authUrl
@@ -544,6 +547,8 @@ Feature: Registry api tests
When method get
Then status 200
* match response.contactDetails == { mobile: '#notpresent', email: '#present', osid: '#present' }
+
+ @envnot=fusionauth
Scenario: Create birth certificate schema, issue credentials then revoke the credential and check for CRUD APIS
# get admin token
* url authUrl
@@ -678,6 +683,7 @@ Feature: Registry api tests
And print response[notificationStudent]
And assert response[notificationStudent] != null
+ @envnot=fusionauth
Scenario: Test unique constraints with nested and composite fields
# create entity
Given url registryUrl
diff --git a/java/middleware/pom.xml b/java/middleware/pom.xml
index c0b099501..2edfd5f10 100644
--- a/java/middleware/pom.xml
+++ b/java/middleware/pom.xml
@@ -1,4 +1,6 @@
-
+
4.0.0
diff --git a/java/middleware/registry-middleware/auth0/pom.xml b/java/middleware/registry-middleware/auth0/pom.xml
new file mode 100644
index 000000000..b36dd6ff2
--- /dev/null
+++ b/java/middleware/registry-middleware/auth0/pom.xml
@@ -0,0 +1,76 @@
+
+
+
+ registry-middleware
+ dev.sunbirdrc
+ 2.0.3
+
+ 4.0.0
+
+ auth0
+
+
+
+
+
+
+
+
+ com.auth0
+ auth0
+ 2.3.0
+
+
+ org.springframework
+ spring-context
+ 5.0.2.RELEASE
+
+
+ org.springframework
+ spring-web
+ 5.0.2.RELEASE
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.32
+ compile
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+ 2.5.0
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.springframework
+ spring-test
+ 5.3.9
+ test
+
+
+ dev.sunbirdrc
+ pojos
+ 2.0.3
+
+
+ dev.sunbirdrc
+ middleware-commons
+ 2.0.3
+
+
+ dev.sunbirdrc
+ identity-provider
+ 2.0.3
+
+
+
+
diff --git a/java/middleware/registry-middleware/auth0/src/main/java/dev/sunbirdrc/auth/auth0/Auth0AdminUtil.java b/java/middleware/registry-middleware/auth0/src/main/java/dev/sunbirdrc/auth/auth0/Auth0AdminUtil.java
new file mode 100644
index 000000000..83bfee83e
--- /dev/null
+++ b/java/middleware/registry-middleware/auth0/src/main/java/dev/sunbirdrc/auth/auth0/Auth0AdminUtil.java
@@ -0,0 +1,200 @@
+package dev.sunbirdrc.auth.auth0;
+
+import com.auth0.client.auth.AuthAPI;
+import com.auth0.client.mgmt.ManagementAPI;
+import com.auth0.client.mgmt.filter.RolesFilter;
+import com.auth0.client.mgmt.filter.UserFilter;
+import com.auth0.exception.Auth0Exception;
+import com.auth0.json.auth.TokenHolder;
+import com.auth0.json.mgmt.permissions.Permission;
+import com.auth0.json.mgmt.resourceserver.ResourceServer;
+import com.auth0.json.mgmt.resourceserver.Scope;
+import com.auth0.json.mgmt.roles.Role;
+import com.auth0.json.mgmt.roles.RolesPage;
+import com.auth0.json.mgmt.users.User;
+import com.auth0.json.mgmt.users.UsersPage;
+import com.auth0.net.TokenRequest;
+import dev.sunbirdrc.pojos.ComponentHealthInfo;
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityProviderConfiguration;
+import org.apache.logging.log4j.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import dev.sunbirdrc.registry.identity_providers.pojos.CreateUserRequest;
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityException;
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityManager;
+import org.springframework.beans.factory.annotation.Value;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import static dev.sunbirdrc.registry.middleware.util.Constants.CONNECTION_FAILURE;
+
+
+public class Auth0AdminUtil implements IdentityManager {
+ private static final Logger logger = LoggerFactory.getLogger(Auth0AdminUtil.class);
+ private static final String EMAIL = "email_id";
+ private static final String ENTITY = "entity";
+ private static final String MOBILE_NUMBER = "mobile_number";
+ private static final String PASSWORD = "password";
+ public static final String SUNBIRD_AUTH0_SERVICE_NAME = "sunbird.auth0.service";
+ private final IdentityProviderConfiguration identityProviderConfiguration;
+
+ @Value("${auth0.resource.server.id}")
+ private String resourceServerId;
+
+ @Value("${auth0.resource.user.connection:Username-Password-Authentication}")
+ private String userConnection;
+
+
+ public Auth0AdminUtil(IdentityProviderConfiguration identityProviderConfiguration) {
+ this.identityProviderConfiguration = identityProviderConfiguration;
+ }
+
+
+ @Override
+ public String createUser(CreateUserRequest createUserRequest) throws IdentityException {
+ logger.info("Creating user with mobile_number : " + createUserRequest.getUserName());
+ try {
+ String token = getToken();
+ ManagementAPI mgmt = ManagementAPI.newBuilder(identityProviderConfiguration.getRealm(), token).build();
+ Optional roleOptional = createOrGetRole(mgmt, createUserRequest);
+ if (roleOptional.isPresent()) {
+ Optional userOptional = createOrGetUser(mgmt, createUserRequest, roleOptional.get());
+ if (userOptional.isPresent()) {
+ return userOptional.get();
+ } else {
+ throw new IdentityException("Creating user failed");
+ }
+ }
+ } catch (Exception e) {
+ logger.error("Error creating user in auth0", e);
+ throw new IdentityException(String.format("Auth0 user creation error %s", e.getMessage()));
+ }
+ return "";
+ }
+
+ private Optional createOrGetUser(ManagementAPI mgmt, CreateUserRequest createUserRequest, String roleId) throws Auth0Exception {
+ try {
+ User userObject = createUserObject(createUserRequest);
+ User userRepresentation = mgmt.users().create(userObject).execute().getBody();
+ assignUserRole(mgmt, roleId, userRepresentation.getId());
+ return Optional.ofNullable(userRepresentation.getId());
+ } catch (Exception e) {
+ logger.error("User creation exception, {}", e.getMessage());
+ }
+ UsersPage usersPage = searchUser(mgmt, createUserRequest);
+ if (usersPage.getItems().size() > 0) {
+ User existingUser = usersPage.getItems().get(0);
+ assignUserRole(mgmt, roleId, existingUser.getId());
+ return Optional.ofNullable(existingUser.getId());
+ }
+ return Optional.empty();
+ }
+
+ private void assignUserRole(ManagementAPI mgmt, String roleId, String userId) throws Auth0Exception {
+ mgmt.roles().assignUsers(roleId, Collections.singletonList(userId)).execute();
+ }
+
+ private UsersPage searchUser(ManagementAPI mgmt, CreateUserRequest createUserRequest) throws Auth0Exception {
+ UserFilter userFilter = new UserFilter();
+ userFilter.withQuery(createUserRequest.getUserName());
+ return mgmt.users().list(userFilter).execute().getBody();
+ }
+
+ private Optional createOrGetRole(ManagementAPI mgmt, CreateUserRequest createUserRequest) throws Auth0Exception {
+ String role = createUserRequest.getEntity();
+ try {
+ Role roleRepresentation = createRole(mgmt, role);
+ addPermission(mgmt, role, roleRepresentation);
+ return Optional.ofNullable(roleRepresentation.getId());
+ } catch (Exception e) {
+ logger.error("Role creation exception, {}", e.getMessage());
+ }
+ RolesPage rolesPage = searchExistingRoles(mgmt, role);
+ if (rolesPage.getItems().size() > 0) {
+ Role existingRoleRepresentation = rolesPage.getItems().get(0);
+ addPermission(mgmt, role, existingRoleRepresentation);
+ return Optional.ofNullable(existingRoleRepresentation.getId());
+ }
+ return Optional.empty();
+ }
+
+ private void addScopeToResourceServer(ManagementAPI mgmt, String role) {
+ try {
+ ResourceServer resourceServer = new ResourceServer();
+ resourceServer.setScopes(Collections.singletonList(new Scope(role)));
+ mgmt.resourceServers().update(resourceServerId, resourceServer).execute();
+ } catch (Exception e) {
+ logger.error("Error adding scopes to resource server, {}", e.getMessage());
+ }
+ }
+
+ private RolesPage searchExistingRoles(ManagementAPI mgmt, String role) throws Auth0Exception {
+ RolesFilter filter = new RolesFilter();
+ filter.withName(role);
+ return mgmt.roles().list(filter).execute().getBody();
+ }
+
+ private Role createRole(ManagementAPI mgmt, String role) throws Auth0Exception {
+ Role roleRepresentation = new Role();
+ roleRepresentation.setName(role);
+ roleRepresentation = mgmt.roles().create(roleRepresentation).execute().getBody();
+ return roleRepresentation;
+ }
+
+ private void addPermission(ManagementAPI mgmt, String role, Role roleRepresentation) throws Auth0Exception {
+ addScopeToResourceServer(mgmt, role);
+ Permission permission = new Permission();
+ permission.setName(role);
+ permission.setResourceServerId(resourceServerId);
+ mgmt.roles().addPermissions(roleRepresentation.getId(), Collections.singletonList(permission)).execute();
+ }
+
+ private User createUserObject(CreateUserRequest createUserRequest) {
+ User user = new User();
+ user.setEmail(createUserRequest.getEmail());
+// user.setPhoneNumber(createUserRequest.getMobile());
+ user.setName(createUserRequest.getUserName());
+ Map userMetadata = new HashMap<>();
+ userMetadata.put(ENTITY, Collections.singletonList(createUserRequest.getEntity()));
+ userMetadata.put(EMAIL, createUserRequest.getEmail());
+ userMetadata.put(MOBILE_NUMBER, createUserRequest.getMobile());
+ user.setUserMetadata(userMetadata);
+ user.setConnection("Username-Password-Authentication");
+ if (!Strings.isBlank(createUserRequest.getPassword())) {
+ user.setPassword(createUserRequest.getPassword().toCharArray());
+ }
+ return user;
+ }
+
+ //TODO: cache token
+ public String getToken() throws Auth0Exception {
+ AuthAPI authAPI = AuthAPI.newBuilder(identityProviderConfiguration.getRealm(),
+ identityProviderConfiguration.getClientId(), identityProviderConfiguration.getClientSecret()).build();
+ TokenRequest tokenRequest = authAPI.requestToken(identityProviderConfiguration.getUrl());
+ TokenHolder holder = tokenRequest.execute().getBody();
+ return holder.getAccessToken();
+
+ }
+
+ @Override
+ public String getServiceName() {
+ return SUNBIRD_AUTH0_SERVICE_NAME;
+ }
+
+ @Override
+ public ComponentHealthInfo getHealthInfo() {
+ if (identityProviderConfiguration.isAuthenticationEnabled()) {
+ try {
+ //TODO: check auth0 status
+ return new ComponentHealthInfo(getServiceName(), true);
+ } catch (Exception e) {
+ return new ComponentHealthInfo(getServiceName(), false, CONNECTION_FAILURE, e.getMessage());
+ }
+ } else {
+ return new ComponentHealthInfo(getServiceName(), true, "AUTHENTICATION_ENABLED", "false");
+ }
+ }
+}
diff --git a/java/middleware/registry-middleware/auth0/src/main/java/dev/sunbirdrc/auth/auth0/Auth0ProviderImpl.java b/java/middleware/registry-middleware/auth0/src/main/java/dev/sunbirdrc/auth/auth0/Auth0ProviderImpl.java
new file mode 100644
index 000000000..dda5d5d2c
--- /dev/null
+++ b/java/middleware/registry-middleware/auth0/src/main/java/dev/sunbirdrc/auth/auth0/Auth0ProviderImpl.java
@@ -0,0 +1,12 @@
+package dev.sunbirdrc.auth.auth0;
+
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityManager;
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityProviderConfiguration;
+import dev.sunbirdrc.registry.identity_providers.providers.IdentityProvider;
+
+public class Auth0ProviderImpl implements IdentityProvider {
+ @Override
+ public IdentityManager createManager(IdentityProviderConfiguration identityProviderConfiguration) {
+ return new Auth0AdminUtil(identityProviderConfiguration);
+ }
+}
diff --git a/java/middleware/registry-middleware/auth0/src/main/resources/META-INF/services/dev.sunbirdrc.registry.identity_providers.providers.IdentityProvider b/java/middleware/registry-middleware/auth0/src/main/resources/META-INF/services/dev.sunbirdrc.registry.identity_providers.providers.IdentityProvider
new file mode 100644
index 000000000..0baa94cb6
--- /dev/null
+++ b/java/middleware/registry-middleware/auth0/src/main/resources/META-INF/services/dev.sunbirdrc.registry.identity_providers.providers.IdentityProvider
@@ -0,0 +1 @@
+dev.sunbirdrc.auth.auth0.Auth0ProviderImpl
diff --git a/java/middleware/registry-middleware/authorization/pom.xml b/java/middleware/registry-middleware/authorization/pom.xml
index 6273ffb35..65431a960 100644
--- a/java/middleware/registry-middleware/authorization/pom.xml
+++ b/java/middleware/registry-middleware/authorization/pom.xml
@@ -20,12 +20,12 @@
org.springframework.boot
spring-boot-starter-web
- 2.0.1.RELEASE
+ 2.3.12.RELEASE
- org.springframework.security
- spring-security-core
- 5.0.12.RELEASE
+ org.springframework.boot
+ spring-boot-starter-security
+ 2.3.12.RELEASE
io.jsonwebtoken
@@ -96,59 +96,37 @@
2.0.0.RELEASE
test
+
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+ 2.3.1.RELEASE
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ 2.3.12.RELEASE
+ true
+
+
+ org.springframework.security
+ spring-security-oauth2-resource-server
+ 5.3.9.RELEASE
+
+
+ org.springframework.security
+ spring-security-oauth2-jose
+ 5.3.9.RELEASE
+
+
+ jakarta.validation
+ jakarta.validation-api
+ 2.0.2
+
-
- org.jacoco
- jacoco-maven-plugin
- ${jacoco.version}
-
-
- prepare-agent
-
- prepare-agent
-
-
-
- report
- prepare-package
-
- report
-
-
-
- post-unit-test
- test
-
- report
-
-
-
- target/jacoco.exec
-
- target/jacoco-ut
-
-
-
-
-
- target/jacoco.exec
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- ${runSuite}
-
- 0
-
-
-
\ No newline at end of file
+
diff --git a/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/CustomJwtAuthenticationConverter.java b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/CustomJwtAuthenticationConverter.java
new file mode 100644
index 000000000..9f53e7b35
--- /dev/null
+++ b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/CustomJwtAuthenticationConverter.java
@@ -0,0 +1,65 @@
+package dev.sunbirdrc.registry.authorization;
+
+import com.jayway.jsonpath.DocumentContext;
+import com.jayway.jsonpath.JsonPath;
+import dev.sunbirdrc.registry.authorization.pojos.UserToken;
+import dev.sunbirdrc.registry.authorization.pojos.OAuth2Properties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.oauth2.jwt.Jwt;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+class CustomJwtAuthenticationConverter implements Converter {
+ private static final Logger logger = LoggerFactory.getLogger(CustomJwtAuthenticationConverter.class);
+
+ private final OAuth2Properties oAuth2Properties;
+
+ public CustomJwtAuthenticationConverter(OAuth2Properties oAuth2Properties) {
+ this.oAuth2Properties = oAuth2Properties;
+ }
+
+ @Override
+ public AbstractAuthenticationToken convert(Jwt source) {
+ try {
+ DocumentContext documentContext = JsonPath.parse(source.getClaims());
+ List roles = getValue(documentContext, oAuth2Properties.getRolesPath(), ArrayList.class);
+ String email = getValue(documentContext, oAuth2Properties.getEmailPath(), String.class);
+ Map consentFields = getValue(documentContext, oAuth2Properties.getConsentPath(), Map.class);
+ List entities = getValue(documentContext, oAuth2Properties.getEntityPath(), ArrayList.class);
+ String userId = getValue(documentContext, oAuth2Properties.getUserIdPath(), String.class);
+ return new UserToken(source, userId, email, consentFields, entities,
+ roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));
+ } catch (Exception e) {
+ logger.error("Error while extracting claim", e);
+ return new UserToken(source, "", "", Collections.emptyMap(), Collections.emptyList(), Collections.emptyList());
+ }
+
+ }
+
+ private T getValue(DocumentContext documentContext, String path, Class type) {
+ try {
+ T value = documentContext.read(path, type);
+ return type.cast(value);
+ } catch (Exception e) {
+ logger.debug("Fetching {} from token claims failed", path, e);
+ }
+ return getDefaultValue(type);
+ }
+
+ private T getDefaultValue(Class type) {
+ if (String.class.equals(type)) {
+ return (T) "";
+ } else if (Map.class.equals(type)) {
+ return (T) Collections.emptyMap();
+ } else if (ArrayList.class.equals(type)) {
+ return (T) Collections.emptyList();
+ }
+ return null;
+ }
+
+}
diff --git a/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/SchemaAuthFilter.java b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/SchemaAuthFilter.java
new file mode 100644
index 000000000..beb58966f
--- /dev/null
+++ b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/SchemaAuthFilter.java
@@ -0,0 +1,60 @@
+package dev.sunbirdrc.registry.authorization;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class SchemaAuthFilter implements Filter {
+ private static final Logger logger = LoggerFactory.getLogger(SchemaAuthFilter.class);
+ private static final String INVITE_URL_ENDPOINT = "/invite";
+
+ private final Set anonymousInviteSchemas = new HashSet<>();
+ private final Set anonymousSchemas = new HashSet<>();
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
+ HttpServletRequest request = (HttpServletRequest) servletRequest;
+ try {
+ if (request.getRequestURI().contains(INVITE_URL_ENDPOINT) &&
+ anonymousInviteSchemas.stream().anyMatch(request.getRequestURI()::contains)) {
+ servletRequest.getRequestDispatcher(((HttpServletRequest) servletRequest).getServletPath()).forward(servletRequest, servletResponse);
+ return;
+ } else if (!request.getRequestURI().contains(INVITE_URL_ENDPOINT) && anonymousSchemas.stream().anyMatch(request.getRequestURI()::contains)) {
+ servletRequest.getRequestDispatcher(((HttpServletRequest) servletRequest).getServletPath()).forward(servletRequest, servletResponse);
+ return;
+ }
+ filterChain.doFilter(servletRequest, servletResponse);
+ } catch (Exception e) {
+ logger.error("Exception while applying security filters: ", e);
+ throw e;
+ }
+ }
+
+ public void appendAnonymousInviteSchema(String schema) {
+ anonymousInviteSchemas.add(schema);
+ }
+
+ public void appendAnonymousSchema(String schema) {
+ anonymousSchemas.add(schema);
+ }
+
+
+ public void appendAnonymousInviteSchema(List entitiesWithAnonymousInviteRoles) {
+ anonymousInviteSchemas.addAll(entitiesWithAnonymousInviteRoles);
+ }
+
+ public void appendAnonymousSchema(List entitiesWithAnonymousManageRoles) {
+ anonymousSchemas.addAll(entitiesWithAnonymousManageRoles);
+ }
+
+ public void removeSchema(String schema) {
+ anonymousSchemas.remove(schema);
+ anonymousInviteSchemas.remove(schema);
+ }
+}
diff --git a/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/SecurityConfig.java b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/SecurityConfig.java
new file mode 100644
index 000000000..121a79d79
--- /dev/null
+++ b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/SecurityConfig.java
@@ -0,0 +1,71 @@
+package dev.sunbirdrc.registry.authorization;
+
+import dev.sunbirdrc.registry.authorization.pojos.OAuth2Configuration;
+import dev.sunbirdrc.registry.authorization.pojos.OAuth2Resources;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.oauth2.jwt.JwtDecoders;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationProvider;
+import org.springframework.security.oauth2.server.resource.authentication.JwtIssuerAuthenticationManagerResolver;
+import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+@EnableWebSecurity
+@ConditionalOnProperty(name = "authentication.enabled",havingValue = "true",matchIfMissing = false)
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Value("${authentication.enabled:true}")
+ boolean authenticationEnabled;
+
+ @Autowired
+ private OAuth2Configuration oAuth2Configuration;
+
+ @Autowired
+ private SchemaAuthFilter schemaAuthFilter;
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ HttpSecurity httpConfig = http.csrf().disable();
+ if (authenticationEnabled) {
+ Map authenticationManagers = new HashMap<>();
+ this.oAuth2Configuration.getResources().forEach(issuer -> addManager(authenticationManagers, issuer));
+ httpConfig
+ .addFilterBefore(schemaAuthFilter, WebAsyncManagerIntegrationFilter.class)
+ .authorizeRequests(auth -> auth
+ .antMatchers("/**/invite", "/health", "/error",
+ "/_schemas/**", "/**/templates/**", "/**/*.json", "/**/verify",
+ "/swagger-ui", "/**/search", "/**/attestation/**",
+ "/api/docs/swagger.json", "/api/docs/*.json", "/plugin/**", "/swagger-ui.html")
+ .permitAll()
+ )
+ .authorizeRequests(auth -> auth
+ .anyRequest()
+ .authenticated())
+ .oauth2ResourceServer(oauth2ResourceServer -> oauth2ResourceServer
+ .authenticationManagerResolver(new JwtIssuerAuthenticationManagerResolver(authenticationManagers::get)));
+ } else {
+ httpConfig.authorizeRequests(auth -> auth
+ .anyRequest()
+ .permitAll()
+ );
+ }
+
+ }
+
+ private void addManager(Map authenticationManagers, OAuth2Resources issuer) {
+ JwtAuthenticationProvider authenticationProvider = new JwtAuthenticationProvider(JwtDecoders.fromOidcIssuerLocation(issuer.getUri()));
+ authenticationProvider.setJwtAuthenticationConverter(new CustomJwtAuthenticationConverter(issuer.getProperties()));
+ authenticationManagers.put(issuer.getUri(), authenticationProvider::authenticate);
+ }
+
+}
+
diff --git a/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/pojos/OAuth2Configuration.java b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/pojos/OAuth2Configuration.java
new file mode 100644
index 000000000..4bdca4aa4
--- /dev/null
+++ b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/pojos/OAuth2Configuration.java
@@ -0,0 +1,19 @@
+package dev.sunbirdrc.registry.authorization.pojos;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.List;
+
+@Validated
+@Configuration
+@ConfigurationProperties(prefix = "oauth2")
+@Component
+@Data
+public class OAuth2Configuration {
+ List resources;
+
+}
diff --git a/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/pojos/OAuth2Properties.java b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/pojos/OAuth2Properties.java
new file mode 100644
index 000000000..cca41a580
--- /dev/null
+++ b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/pojos/OAuth2Properties.java
@@ -0,0 +1,13 @@
+package dev.sunbirdrc.registry.authorization.pojos;
+
+
+import lombok.Data;
+
+@Data
+public class OAuth2Properties {
+ private String rolesPath = "realm_access.roles";
+ private String emailPath = "email";
+ private String consentPath = "consent";
+ private String entityPath = "entity";
+ private String userIdPath = "sub";
+}
diff --git a/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/pojos/OAuth2Resources.java b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/pojos/OAuth2Resources.java
new file mode 100644
index 000000000..5ba009ebe
--- /dev/null
+++ b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/pojos/OAuth2Resources.java
@@ -0,0 +1,13 @@
+package dev.sunbirdrc.registry.authorization.pojos;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class OAuth2Resources {
+ @NotBlank
+ private String uri;
+ private OAuth2Properties properties = new OAuth2Properties();
+
+}
diff --git a/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/pojos/UserToken.java b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/pojos/UserToken.java
new file mode 100644
index 000000000..7a8591a96
--- /dev/null
+++ b/java/middleware/registry-middleware/authorization/src/main/java/dev/sunbirdrc/registry/authorization/pojos/UserToken.java
@@ -0,0 +1,40 @@
+package dev.sunbirdrc.registry.authorization.pojos;
+
+import lombok.Getter;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.oauth2.jwt.Jwt;
+
+import java.security.Principal;
+import java.util.List;
+import java.util.Map;
+
+@Getter
+public class UserToken extends AbstractAuthenticationToken {
+ private final List entities;
+ private final Jwt source;
+ private String userId;
+ private final String email;
+
+ private final Map consentFields;
+
+ public UserToken(Jwt source, String userId, String email, Map consentFields, List entities, List authorities) {
+ super(authorities);
+ this.source = source;
+ this.userId = userId;
+ this.email = email;
+ this.consentFields = consentFields;
+ this.entities = entities;
+ this.setAuthenticated(true);
+ }
+
+ @Override
+ public Object getCredentials() {
+ return null;
+ }
+
+ @Override
+ public Object getPrincipal() {
+ return (Principal) this.source::getId;
+ }
+}
diff --git a/java/middleware/registry-middleware/authorization/src/test/java/dev/sunbirdrc/registry/authorization/CustomJwtAuthenticationConverterTest.java b/java/middleware/registry-middleware/authorization/src/test/java/dev/sunbirdrc/registry/authorization/CustomJwtAuthenticationConverterTest.java
new file mode 100644
index 000000000..9e18849f5
--- /dev/null
+++ b/java/middleware/registry-middleware/authorization/src/test/java/dev/sunbirdrc/registry/authorization/CustomJwtAuthenticationConverterTest.java
@@ -0,0 +1,77 @@
+package dev.sunbirdrc.registry.authorization;
+
+import dev.sunbirdrc.registry.authorization.pojos.OAuth2Properties;
+import dev.sunbirdrc.registry.authorization.pojos.UserToken;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.oauth2.jwt.Jwt;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CustomJwtAuthenticationConverterTest {
+ @Test
+ public void shouldExtractValuesFromJWTClaim() {
+ OAuth2Properties oAuth2Properties = new OAuth2Properties();
+ oAuth2Properties.setUserIdPath("sub");
+ oAuth2Properties.setRolesPath("user.roles");
+ oAuth2Properties.setConsentPath("user.consent");
+ oAuth2Properties.setEmailPath("user.email");
+ oAuth2Properties.setEntityPath("entity");
+ CustomJwtAuthenticationConverter converter = new CustomJwtAuthenticationConverter(oAuth2Properties);
+ Jwt jwt = mock(Jwt.class);
+ Map claims = new HashMap<>();
+ claims.put("sub", "1234");
+ Map userMap = new HashMap<>();
+ userMap.put("roles", Collections.singletonList("admin"));
+ Map consentMap = new HashMap<>();
+ consentMap.put("name", 1);
+ userMap.put("consent", consentMap);
+ userMap.put("email", "1234@mail.com");
+ claims.put("user", userMap);
+ claims.put("entity", Arrays.asList("Student", "Teacher"));
+ when(jwt.getClaims()).thenReturn(claims);
+ AbstractAuthenticationToken authenticationToken = converter.convert(jwt);
+ assert authenticationToken != null;
+ Assert.assertEquals("1234", ((UserToken) authenticationToken).getUserId());
+ Assert.assertEquals("{name=1}", ((UserToken) authenticationToken).getConsentFields().toString());
+ Assert.assertEquals("1234@mail.com", ((UserToken) authenticationToken).getEmail());
+ Assert.assertEquals("[Student, Teacher]", ((UserToken) authenticationToken).getEntities().toString());
+ Assert.assertEquals("[admin]", authenticationToken.getAuthorities().toString());
+ }
+
+ @Test
+ public void shouldHandleInvalidValuesWhileExtractionWithDefaultValues() {
+ OAuth2Properties oAuth2Properties = new OAuth2Properties();
+ oAuth2Properties.setUserIdPath("sub");
+ oAuth2Properties.setRolesPath("user.roles");
+ oAuth2Properties.setConsentPath("user.consent");
+ oAuth2Properties.setEmailPath("user.email");
+ oAuth2Properties.setEntityPath("entity");
+ CustomJwtAuthenticationConverter converter = new CustomJwtAuthenticationConverter(oAuth2Properties);
+ Jwt jwt = mock(Jwt.class);
+ Map claims = new HashMap<>();
+ claims.put("sub", "1234");
+ Map userMap = new HashMap<>();
+ userMap.put("roles", "admin");
+ userMap.put("email", "1234@mail.com");
+ claims.put("user", userMap);
+ when(jwt.getClaims()).thenReturn(claims);
+ AbstractAuthenticationToken authenticationToken = converter.convert(jwt);
+ assert authenticationToken != null;
+ Assert.assertEquals("1234", ((UserToken) authenticationToken).getUserId());
+ Assert.assertEquals("{}", ((UserToken) authenticationToken).getConsentFields().toString());
+ Assert.assertEquals("1234@mail.com", ((UserToken) authenticationToken).getEmail());
+ Assert.assertEquals("[]", ((UserToken) authenticationToken).getEntities().toString());
+ Assert.assertEquals("[]", authenticationToken.getAuthorities().toString());
+ }
+}
diff --git a/java/middleware/registry-middleware/generic-iam/pom.xml b/java/middleware/registry-middleware/generic-iam/pom.xml
new file mode 100644
index 000000000..e52c4e6bf
--- /dev/null
+++ b/java/middleware/registry-middleware/generic-iam/pom.xml
@@ -0,0 +1,72 @@
+
+
+
+ registry-middleware
+ dev.sunbirdrc
+ 2.0.3
+
+ 4.0.0
+
+ generic-iam
+
+
+
+
+
+
+
+
+
+ org.springframework
+ spring-context
+ 5.0.2.RELEASE
+
+
+ org.springframework
+ spring-web
+ 5.0.2.RELEASE
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.32
+ compile
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+ 2.5.0
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.springframework
+ spring-test
+ 5.3.9
+ test
+
+
+ dev.sunbirdrc
+ pojos
+ 2.0.3
+
+
+ dev.sunbirdrc
+ middleware-commons
+ 2.0.3
+
+
+ dev.sunbirdrc
+ identity-provider
+ 2.0.3
+
+
+
+
diff --git a/java/middleware/registry-middleware/generic-iam/src/main/java/dev/sunbirdrc/auth/genericiam/AdminUtil.java b/java/middleware/registry-middleware/generic-iam/src/main/java/dev/sunbirdrc/auth/genericiam/AdminUtil.java
new file mode 100644
index 000000000..0310fe652
--- /dev/null
+++ b/java/middleware/registry-middleware/generic-iam/src/main/java/dev/sunbirdrc/auth/genericiam/AdminUtil.java
@@ -0,0 +1,67 @@
+package dev.sunbirdrc.auth.genericiam;
+
+import dev.sunbirdrc.pojos.ComponentHealthInfo;
+import dev.sunbirdrc.registry.identity_providers.pojos.*;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Collections;
+import java.util.Objects;
+
+import static dev.sunbirdrc.registry.middleware.util.Constants.CONNECTION_FAILURE;
+
+
+public class AdminUtil implements IdentityManager {
+ public static final String SUNBIRD_GENERIC_IAM_SERVICE_NAME = "sunbird.generic-iam.service";
+ private static final Logger logger = LoggerFactory.getLogger(AdminUtil.class);
+ private final IdentityProviderConfiguration identityProviderConfiguration;
+
+ private final RestTemplate restTemplate;
+
+ private final String iamServiceURL;
+
+ public AdminUtil(IdentityProviderConfiguration identityProviderConfiguration) {
+ this.identityProviderConfiguration = identityProviderConfiguration;
+ this.restTemplate = new RestTemplate();
+ this.iamServiceURL = System.getenv()
+ .getOrDefault("sunbird_sso_url", "http://localhost:3990/fusionauth/api/v1/user");
+ }
+
+
+ @Override
+ public String createUser(CreateUserRequest createUserRequest) throws IdentityException {
+ logger.info("Creating user with mobile_number : " + createUserRequest.getUserName());
+ ResponseEntity response = this.restTemplate.postForEntity(this.iamServiceURL,
+ createUserRequest, CreateUserResponse.class);
+ if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null &&
+ !StringUtils.isEmpty(response.getBody().getUserId())) {
+ return response.getBody().getUserId();
+ }
+ logger.error("Error creating user in IAM service");
+ throw new IdentityException(String.format("User creation error %s", createUserRequest));
+ }
+
+
+ @Override
+ public String getServiceName() {
+ return SUNBIRD_GENERIC_IAM_SERVICE_NAME;
+ }
+
+ @Override
+ public ComponentHealthInfo getHealthInfo() {
+ if (identityProviderConfiguration.isAuthenticationEnabled()) {
+ try {
+ //TODO: check auth0 status
+ return new ComponentHealthInfo(getServiceName(), true);
+ } catch (Exception e) {
+ return new ComponentHealthInfo(getServiceName(), false, CONNECTION_FAILURE, e.getMessage());
+ }
+ } else {
+ return new ComponentHealthInfo(getServiceName(), true, "AUTHENTICATION_ENABLED", "false");
+ }
+ }
+}
diff --git a/java/middleware/registry-middleware/generic-iam/src/main/java/dev/sunbirdrc/auth/genericiam/AuthProviderImpl.java b/java/middleware/registry-middleware/generic-iam/src/main/java/dev/sunbirdrc/auth/genericiam/AuthProviderImpl.java
new file mode 100644
index 000000000..443e87693
--- /dev/null
+++ b/java/middleware/registry-middleware/generic-iam/src/main/java/dev/sunbirdrc/auth/genericiam/AuthProviderImpl.java
@@ -0,0 +1,12 @@
+package dev.sunbirdrc.auth.genericiam;
+
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityManager;
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityProviderConfiguration;
+import dev.sunbirdrc.registry.identity_providers.providers.IdentityProvider;
+
+public class AuthProviderImpl implements IdentityProvider {
+ @Override
+ public IdentityManager createManager(IdentityProviderConfiguration identityProviderConfiguration) {
+ return new AdminUtil(identityProviderConfiguration);
+ }
+}
diff --git a/java/middleware/registry-middleware/generic-iam/src/main/resources/META-INF/services/dev.sunbirdrc.registry.identity_providers.providers.IdentityProvider b/java/middleware/registry-middleware/generic-iam/src/main/resources/META-INF/services/dev.sunbirdrc.registry.identity_providers.providers.IdentityProvider
new file mode 100644
index 000000000..ac8797b7a
--- /dev/null
+++ b/java/middleware/registry-middleware/generic-iam/src/main/resources/META-INF/services/dev.sunbirdrc.registry.identity_providers.providers.IdentityProvider
@@ -0,0 +1 @@
+dev.sunbirdrc.auth.genericiam.AuthProviderImpl
diff --git a/java/middleware/registry-middleware/identity-provider/pom.xml b/java/middleware/registry-middleware/identity-provider/pom.xml
new file mode 100644
index 000000000..16ef44352
--- /dev/null
+++ b/java/middleware/registry-middleware/identity-provider/pom.xml
@@ -0,0 +1,30 @@
+
+ 4.0.0
+
+ identity-provider
+ 2.0.3
+ Identity Provider
+
+
+ dev.sunbirdrc
+ registry-middleware
+ 2.0.3
+
+
+
+
+
+ dev.sunbirdrc
+ pojos
+ 2.0.3
+ compile
+
+
+
+
+
+
+
+
+
diff --git a/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/CreateUserRequest.java b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/CreateUserRequest.java
new file mode 100644
index 000000000..7b90ad67d
--- /dev/null
+++ b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/CreateUserRequest.java
@@ -0,0 +1,22 @@
+package dev.sunbirdrc.registry.identity_providers.pojos;
+
+
+import lombok.Data;
+
+@Data
+public class CreateUserRequest {
+ private final String userName;
+ private final String email;
+ private final String mobile;
+ private final String entity;
+
+ private final String password;
+ public CreateUserRequest(String entity, String userName, String email, String mobile, String password) {
+ this.userName = userName;
+ this.email = email;
+ this.mobile = mobile;
+ this.entity = entity;
+ this.password = password;
+ }
+
+}
diff --git a/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/CreateUserResponse.java b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/CreateUserResponse.java
new file mode 100644
index 000000000..bf714df9b
--- /dev/null
+++ b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/CreateUserResponse.java
@@ -0,0 +1,16 @@
+package dev.sunbirdrc.registry.identity_providers.pojos;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class CreateUserResponse {
+ private String userId;
+ private String status;
+ private String message;
+
+}
diff --git a/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/IdentityException.java b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/IdentityException.java
new file mode 100644
index 000000000..e8e1a967b
--- /dev/null
+++ b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/IdentityException.java
@@ -0,0 +1,8 @@
+package dev.sunbirdrc.registry.identity_providers.pojos;
+
+public class IdentityException extends Exception {
+
+ public IdentityException(String message) {
+ super(message);
+ }
+}
diff --git a/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/IdentityManager.java b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/IdentityManager.java
new file mode 100644
index 000000000..2a38a9057
--- /dev/null
+++ b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/IdentityManager.java
@@ -0,0 +1,7 @@
+package dev.sunbirdrc.registry.identity_providers.pojos;
+
+import dev.sunbirdrc.pojos.HealthIndicator;
+
+public interface IdentityManager extends HealthIndicator {
+ String createUser(CreateUserRequest createUserRequest) throws IdentityException;
+}
diff --git a/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/IdentityProviderConfiguration.java b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/IdentityProviderConfiguration.java
new file mode 100644
index 000000000..5456e303f
--- /dev/null
+++ b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/IdentityProviderConfiguration.java
@@ -0,0 +1,38 @@
+package dev.sunbirdrc.registry.identity_providers.pojos;
+
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+@Getter
+public class IdentityProviderConfiguration {
+ @Value("${identity.provider}")
+ private String provider;
+ @Value("${identity.url}")
+ private String url;
+ @Value("${identity.realm}")
+ private String realm;
+ @Value("${identity.client_id}")
+ private String clientId;
+ @Value("${identity.client_secret}")
+ private String clientSecret;
+ @Value("${identity.set_default_password}")
+ private Boolean setDefaultPassword;
+ @Value("${identity.default_password}")
+ private String defaultPassword;
+ @Value("${identity.user_actions}")
+ private List userActions;
+
+ @Value("${httpConnection.maxConnections:5}")
+ private int httpMaxConnections;
+
+ @Value("${authentication.enabled:true}")
+ boolean authenticationEnabled;
+
+ public Boolean setDefaultPassword() {
+ return setDefaultPassword;
+ }
+}
diff --git a/java/middleware/registry-middleware/keycloak/src/main/java/dev/sunbirdrc/keycloak/OwnerCreationException.java b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/OwnerCreationException.java
similarity index 77%
rename from java/middleware/registry-middleware/keycloak/src/main/java/dev/sunbirdrc/keycloak/OwnerCreationException.java
rename to java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/OwnerCreationException.java
index 8d3ad623c..f296d4969 100644
--- a/java/middleware/registry-middleware/keycloak/src/main/java/dev/sunbirdrc/keycloak/OwnerCreationException.java
+++ b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/pojos/OwnerCreationException.java
@@ -1,9 +1,9 @@
-package dev.sunbirdrc.keycloak;
+package dev.sunbirdrc.registry.identity_providers.pojos;
public class OwnerCreationException extends Exception {
/**
- *
+ *
*/
private static final long serialVersionUID = 8690094725383702979L;
diff --git a/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/providers/IdentityProvider.java b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/providers/IdentityProvider.java
new file mode 100644
index 000000000..c9855d33f
--- /dev/null
+++ b/java/middleware/registry-middleware/identity-provider/src/main/java/dev/sunbirdrc/registry/identity_providers/providers/IdentityProvider.java
@@ -0,0 +1,8 @@
+package dev.sunbirdrc.registry.identity_providers.providers;
+
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityManager;
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityProviderConfiguration;
+
+public interface IdentityProvider {
+ IdentityManager createManager(IdentityProviderConfiguration identityProviderConfiguration);
+}
diff --git a/java/middleware/registry-middleware/keycloak/pom.xml b/java/middleware/registry-middleware/keycloak/pom.xml
index 84868de9e..f134c6ce4 100644
--- a/java/middleware/registry-middleware/keycloak/pom.xml
+++ b/java/middleware/registry-middleware/keycloak/pom.xml
@@ -13,13 +13,7 @@
-
- org.keycloak.bom
- keycloak-adapter-bom
- 11.0.2
- pom
- import
-
+
@@ -72,5 +66,11 @@
middleware-commons
2.0.3
+
+ dev.sunbirdrc
+ identity-provider
+ 2.0.3
+
+
-
\ No newline at end of file
+
diff --git a/java/middleware/registry-middleware/keycloak/src/main/java/dev/sunbirdrc/keycloak/KeycloakAdminUtil.java b/java/middleware/registry-middleware/keycloak/src/main/java/dev/sunbirdrc/auth/keycloak/KeycloakAdminUtil.java
similarity index 57%
rename from java/middleware/registry-middleware/keycloak/src/main/java/dev/sunbirdrc/keycloak/KeycloakAdminUtil.java
rename to java/middleware/registry-middleware/keycloak/src/main/java/dev/sunbirdrc/auth/keycloak/KeycloakAdminUtil.java
index 9705aa932..f48d4f4c9 100644
--- a/java/middleware/registry-middleware/keycloak/src/main/java/dev/sunbirdrc/keycloak/KeycloakAdminUtil.java
+++ b/java/middleware/registry-middleware/keycloak/src/main/java/dev/sunbirdrc/auth/keycloak/KeycloakAdminUtil.java
@@ -1,6 +1,7 @@
-package dev.sunbirdrc.keycloak;
+package dev.sunbirdrc.auth.keycloak;
import dev.sunbirdrc.pojos.ComponentHealthInfo;
+import dev.sunbirdrc.registry.identity_providers.pojos.*;
import dev.sunbirdrc.pojos.HealthIndicator;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.keycloak.OAuth2Constants;
@@ -13,10 +14,6 @@
import org.keycloak.representations.idm.UserRepresentation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.PropertySource;
-import org.springframework.stereotype.Component;
import java.util.*;
import javax.ws.rs.NotFoundException;
@@ -26,91 +23,64 @@
import static dev.sunbirdrc.registry.middleware.util.Constants.SUNBIRD_KEYCLOAK_SERVICE_NAME;
-@Component
-@PropertySource(value = "classpath:application.yml", ignoreResourceNotFound = true)
-public class KeycloakAdminUtil implements HealthIndicator {
+public class KeycloakAdminUtil implements IdentityManager {
private static final Logger logger = LoggerFactory.getLogger(KeycloakAdminUtil.class);
private static final String EMAIL = "email_id";
private static final String ENTITY = "entity";
private static final String MOBILE_NUMBER = "mobile_number";
private static final String PASSWORD = "password";
-
-
- private String realm;
- private String adminClientSecret;
- private String adminClientId;
- private String authURL;
- private String defaultPassword;
- private boolean setDefaultPassword;
- private List emailActions;
private final Keycloak keycloak;
- private boolean authenticationEnabled;
-
- @Autowired
- public KeycloakAdminUtil(
- @Value("${authentication.enabled}")
- boolean authenticationEnabled,
- @Value("${keycloak.realm:}") String realm,
- @Value("${keycloak-admin.client-secret:}") String adminClientSecret,
- @Value("${keycloak-admin.client-id:}") String adminClientId,
- @Value("${keycloak-user.default-password:}") String defaultPassword,
- @Value("${keycloak-user.set-default-password:false}") boolean setDefaultPassword,
- @Value("${keycloak.auth-server-url:}") String authURL,
- @Value("${keycloak-user.email-actions:}") List emailActions,
- @Value("${httpConnection.maxConnections:5}") int httpMaxConnections) {
- this.authenticationEnabled = authenticationEnabled;
- this.realm = realm;
- this.adminClientSecret = adminClientSecret;
- this.adminClientId = adminClientId;
- this.authURL = authURL;
- this.defaultPassword = defaultPassword;
- this.setDefaultPassword = setDefaultPassword;
- this.emailActions = emailActions;
- this.keycloak = buildKeycloak(httpMaxConnections);
+
+ private final IdentityProviderConfiguration providerConfiguration;
+ public KeycloakAdminUtil(IdentityProviderConfiguration identityProviderConfiguration) {
+ this.providerConfiguration = identityProviderConfiguration;
+ this.keycloak = buildKeycloak(identityProviderConfiguration);
}
- private Keycloak buildKeycloak(int httpMaxConnections) {
+ private Keycloak buildKeycloak(IdentityProviderConfiguration configuration) {
return KeycloakBuilder.builder()
- .serverUrl(authURL)
- .realm(realm)
+ .serverUrl(configuration.getUrl())
+ .realm(configuration.getRealm())
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
- .clientId(adminClientId)
- .clientSecret(adminClientSecret)
+ .clientId(configuration.getClientId())
+ .clientSecret(configuration.getClientSecret())
.resteasyClient(
new ResteasyClientBuilder()
- .connectionPoolSize(httpMaxConnections).build()
+ .connectionPoolSize(configuration.getHttpMaxConnections()).build()
)
.build();
}
- public String createUser(String entityName, String userName, String email, String mobile, String password) throws OwnerCreationException {
- logger.info("Creating user with mobile_number : " + userName);
- String groupId = createOrUpdateRealmGroup(entityName);
- UserRepresentation newUser = createUserRepresentation(entityName, userName, email, mobile, password);
- UsersResource usersResource = keycloak.realm(realm).users();
+ @Override
+ public String createUser(CreateUserRequest createUserRequest) throws IdentityException {
+ logger.info("Creating user with mobile_number : " + createUserRequest.getUserName());
+ String groupId = createOrUpdateRealmGroup(createUserRequest.getEntity());
+ UserRepresentation newUser = createUserRepresentation(createUserRequest);
+ UsersResource usersResource = keycloak.realm(providerConfiguration.getRealm()).users();
try (Response response = usersResource.create(newUser)) {
if (response.getStatus() == 201) {
logger.info("Response | Status: {} | Status Info: {}", response.getStatus(), response.getStatusInfo());
logger.info("User ID path" + response.getLocation().getPath());
String userID = response.getLocation().getPath().replaceAll(".*/([^/]+)$", "$1");
logger.info("User ID : " + userID);
- if (!emailActions.isEmpty())
- usersResource.get(userID).executeActionsEmail(emailActions);
+ if (!providerConfiguration.getUserActions().isEmpty()) {
+ usersResource.get(userID).executeActionsEmail(providerConfiguration.getUserActions());
+ }
return userID;
} else if (response.getStatus() == 409) {
- logger.info("UserID: {} exists", userName);
- return updateExistingUserAttributes(entityName, userName, email, mobile, groupId);
+ logger.info("UserID: {} exists", createUserRequest.getUserName());
+ return updateExistingUserAttributes(createUserRequest, groupId);
} else if (response.getStatus() == 500) {
- throw new OwnerCreationException("Keycloak user creation error");
+ throw new IdentityException("Keycloak user creation error");
} else {
- throw new OwnerCreationException("Username already invited / registered");
+ throw new IdentityException("Username already invited / registered");
}
}
}
private String createOrUpdateRealmGroup(String entityName) {
RoleRepresentation roleRepresentation = createOrGetRealmRole(entityName);
- GroupsResource groupsResource = keycloak.realm(realm).groups();
+ GroupsResource groupsResource = keycloak.realm(providerConfiguration.getRealm()).groups();
GroupRepresentation groupRepresentation = new GroupRepresentation();
groupRepresentation.setName(entityName);
Response groupAddResponse = groupsResource.add(groupRepresentation);
@@ -129,7 +99,7 @@ private String createOrUpdateRealmGroup(String entityName) {
}
private RoleRepresentation createOrGetRealmRole(String entityName) {
- RolesResource rolesResource = keycloak.realm(realm).roles();
+ RolesResource rolesResource = keycloak.realm(providerConfiguration.getRealm()).roles();
try {
return rolesResource.get(entityName).toRepresentation();
} catch (NotFoundException ex) {
@@ -143,63 +113,65 @@ private RoleRepresentation createOrGetRealmRole(String entityName) {
return rolesResource.get(entityName).toRepresentation();
}
- private String updateExistingUserAttributes(String entityName, String userName, String email, String mobile,
- String groupId) throws OwnerCreationException {
- Optional userRepresentationOptional = getUserByUsername(userName);
+// private String updateExistingUserAttributes(String entityName, String userName, String email, String mobile,
+ private String updateExistingUserAttributes(CreateUserRequest createUserRequest, String groupId) throws IdentityException {
+ Optional userRepresentationOptional = getUserByUsername(createUserRequest.getUserName());
if (userRepresentationOptional.isPresent()) {
UserResource userResource = userRepresentationOptional.get();
UserRepresentation userRepresentation = userResource.toRepresentation();
- updateUserAttributes(entityName, email, mobile, userRepresentation);
+ updateUserAttributes(createUserRequest, userRepresentation);
List groups = userRepresentation.getGroups();
if (groups == null) {
groups = new ArrayList<>();
}
- if (!groups.contains(entityName)) {
- groups.add(entityName);
+ if (!groups.contains(createUserRequest.getEntity())) {
+ groups.add(createUserRequest.getEntity());
userRepresentation.setGroups(groups);
}
userResource.update(userRepresentation);
userResource.joinGroup(groupId);
return userRepresentation.getId();
} else {
- logger.error("Failed fetching user by username: {}", userName);
- throw new OwnerCreationException("Creating user failed");
+ logger.error("Failed fetching user by username: {}", createUserRequest.getUserName());
+ throw new IdentityException("Creating user failed");
}
}
- private UserRepresentation createUserRepresentation(String entityName, String userName, String email, String mobile, String password) {
+ private UserRepresentation createUserRepresentation(CreateUserRequest createUserRequest) {
UserRepresentation newUser = new UserRepresentation();
newUser.setEnabled(true);
- newUser.setUsername(userName);
- if(Objects.equals(password, "") && this.setDefaultPassword) {
- password = this.defaultPassword;
- }
- if (!Objects.equals(password, "")) {
+ newUser.setUsername(createUserRequest.getUserName());
+ if (!Objects.equals(createUserRequest.getPassword(), "") || providerConfiguration.setDefaultPassword()) {
CredentialRepresentation passwordCredential = new CredentialRepresentation();
- passwordCredential.setValue(password);
+ if (!Objects.equals(createUserRequest.getPassword(), "")) {
+ passwordCredential.setValue(createUserRequest.getPassword());
+ passwordCredential.setTemporary(false);
+ } else {
+ passwordCredential.setValue(providerConfiguration.getDefaultPassword());
+ passwordCredential.setTemporary(true);
+ }
passwordCredential.setType(PASSWORD);
- passwordCredential.setTemporary(false);
newUser.setCredentials(Collections.singletonList(passwordCredential));
}
- newUser.setGroups(Collections.singletonList(entityName));
- newUser.setEmail(email);
- newUser.singleAttribute(MOBILE_NUMBER, mobile);
- newUser.singleAttribute(EMAIL, email);
- newUser.singleAttribute(ENTITY, entityName);
+ newUser.setGroups(Collections.singletonList(createUserRequest.getEntity()));
+ newUser.setEmail(createUserRequest.getEmail());
+ newUser.singleAttribute(MOBILE_NUMBER, createUserRequest.getMobile());
+ newUser.singleAttribute(EMAIL, createUserRequest.getEmail());
+ newUser.singleAttribute(ENTITY, createUserRequest.getEntity());
return newUser;
}
- private void updateUserAttributes(String entityName, String email, String mobile, UserRepresentation userRepresentation) {
+ private void updateUserAttributes(CreateUserRequest createUserRequest, UserRepresentation userRepresentation) {
if (userRepresentation.getAttributes() == null || !userRepresentation.getAttributes().containsKey(ENTITY)) {
- userRepresentation.singleAttribute(ENTITY, entityName);
+ userRepresentation.singleAttribute(ENTITY, createUserRequest.getEntity());
} else {
List entities = userRepresentation.getAttributes().getOrDefault(ENTITY, Collections.emptyList());
- if (!entities.contains(entityName)) {
- entities.add(entityName);
+ if (!entities.contains(createUserRequest.getEntity())) {
+ entities.add(createUserRequest.getEntity());
}
}
- addAttributeIfNotExists(userRepresentation, EMAIL, email);
- addAttributeIfNotExists(userRepresentation, MOBILE_NUMBER, mobile);
+ addAttributeIfNotExists(userRepresentation, EMAIL, createUserRequest.getEmail());
+ addAttributeIfNotExists(userRepresentation, MOBILE_NUMBER, createUserRequest.getMobile());
}
private void addAttributeIfNotExists(UserRepresentation userRepresentation, String key, String value) {
@@ -216,17 +188,17 @@ private void checkIfUserRegisteredForEntity(String entityName, UserRepresentatio
}
private Optional getUserByUsername(String username) {
- List users = keycloak.realm(realm).users().search(username);
+ List users = keycloak.realm(providerConfiguration.getRealm()).users().search(username);
if (users.size() > 0) {
- return Optional.of(keycloak.realm(realm).users().get(users.get(0).getId()));
+ return Optional.of(keycloak.realm(providerConfiguration.getRealm()).users().get(users.get(0).getId()));
}
return Optional.empty();
}
private void addUserToGroup(String groupName, UserRepresentation user) {
- keycloak.realm(realm).groups().groups().stream()
+ keycloak.realm(providerConfiguration.getRealm()).groups().groups().stream()
.filter(g -> g.getName().equals(groupName)).findFirst()
- .ifPresent(g -> keycloak.realm(realm).users().get(user.getId()).joinGroup(g.getId()));
+ .ifPresent(g -> keycloak.realm(providerConfiguration.getRealm()).users().get(user.getId()).joinGroup(g.getId()));
}
@Override
@@ -236,7 +208,7 @@ public String getServiceName() {
@Override
public ComponentHealthInfo getHealthInfo() {
- if (authenticationEnabled) {
+ if (providerConfiguration.isAuthenticationEnabled()) {
try {
return new ComponentHealthInfo(getServiceName(), keycloak.serverInfo().getInfo().getSystemInfo().getUptimeMillis() > 0);
} catch (Exception e) {
diff --git a/java/middleware/registry-middleware/keycloak/src/main/java/dev/sunbirdrc/auth/keycloak/KeycloakProviderImpl.java b/java/middleware/registry-middleware/keycloak/src/main/java/dev/sunbirdrc/auth/keycloak/KeycloakProviderImpl.java
new file mode 100644
index 000000000..023920dde
--- /dev/null
+++ b/java/middleware/registry-middleware/keycloak/src/main/java/dev/sunbirdrc/auth/keycloak/KeycloakProviderImpl.java
@@ -0,0 +1,12 @@
+package dev.sunbirdrc.auth.keycloak;
+
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityManager;
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityProviderConfiguration;
+import dev.sunbirdrc.registry.identity_providers.providers.IdentityProvider;
+
+public class KeycloakProviderImpl implements IdentityProvider {
+ @Override
+ public IdentityManager createManager(IdentityProviderConfiguration identityProviderConfiguration) {
+ return new KeycloakAdminUtil(identityProviderConfiguration);
+ }
+}
diff --git a/java/middleware/registry-middleware/keycloak/src/main/resources/META-INF/services/dev.sunbirdrc.registry.identity_providers.providers.IdentityProvider b/java/middleware/registry-middleware/keycloak/src/main/resources/META-INF/services/dev.sunbirdrc.registry.identity_providers.providers.IdentityProvider
new file mode 100644
index 000000000..a04ad1bd4
--- /dev/null
+++ b/java/middleware/registry-middleware/keycloak/src/main/resources/META-INF/services/dev.sunbirdrc.registry.identity_providers.providers.IdentityProvider
@@ -0,0 +1 @@
+dev.sunbirdrc.auth.keycloak.KeycloakProviderImpl
diff --git a/java/middleware/registry-middleware/pom.xml b/java/middleware/registry-middleware/pom.xml
index 06bcdbd98..2f1b5b26b 100644
--- a/java/middleware/registry-middleware/pom.xml
+++ b/java/middleware/registry-middleware/pom.xml
@@ -11,11 +11,20 @@
2.0.3
middleware-bom
-
+
+
+ dev.sunbirdrc
+ pojos
+ 2.0.3
+
+
authorization
validation
keycloak
workflow
+ identity-provider
+ auth0
+ generic-iam
diff --git a/java/middleware/registry-middleware/validation/src/main/java/dev/sunbirdrc/validators/IValidate.java b/java/middleware/registry-middleware/validation/src/main/java/dev/sunbirdrc/validators/IValidate.java
index 6395be8bf..adddff028 100644
--- a/java/middleware/registry-middleware/validation/src/main/java/dev/sunbirdrc/validators/IValidate.java
+++ b/java/middleware/registry-middleware/validation/src/main/java/dev/sunbirdrc/validators/IValidate.java
@@ -21,4 +21,5 @@ public interface IValidate {
void addDefinitions(JsonNode schema) throws IOException;
void removeDefinition(JsonNode jsonNode);
+ void removeDefinition(String schema);
}
diff --git a/java/middleware/registry-middleware/workflow/pom.xml b/java/middleware/registry-middleware/workflow/pom.xml
index 3831e7ab7..b18e5dad5 100644
--- a/java/middleware/registry-middleware/workflow/pom.xml
+++ b/java/middleware/registry-middleware/workflow/pom.xml
@@ -24,11 +24,6 @@
middleware-commons
2.0.3
-
- dev.sunbirdrc
- keycloak
- 2.0.3
-
junit
junit
@@ -50,6 +45,12 @@
drools-decisiontables
${drools.version}
+
+ dev.sunbirdrc
+ identity-provider
+ 2.0.3
+ compile
+
-
\ No newline at end of file
+
diff --git a/java/middleware/registry-middleware/workflow/src/main/java/dev/sunbirdrc/workflow/RuleEngineService.java b/java/middleware/registry-middleware/workflow/src/main/java/dev/sunbirdrc/workflow/RuleEngineService.java
index 0339d5111..23a1c2e3e 100644
--- a/java/middleware/registry-middleware/workflow/src/main/java/dev/sunbirdrc/workflow/RuleEngineService.java
+++ b/java/middleware/registry-middleware/workflow/src/main/java/dev/sunbirdrc/workflow/RuleEngineService.java
@@ -2,7 +2,6 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
-import dev.sunbirdrc.keycloak.KeycloakAdminUtil;
import dev.sunbirdrc.pojos.OwnershipsAttributes;
import dev.sunbirdrc.registry.middleware.util.JSONUtil;
import dev.sunbirdrc.registry.middleware.util.OSSystemFields;
@@ -10,6 +9,7 @@
import org.kie.api.runtime.StatelessKieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityManager;
import java.util.List;
@@ -18,25 +18,25 @@
@Service
public class RuleEngineService {
private final KieContainer kieContainer;
- private final KeycloakAdminUtil keycloakAdminUtil;
+ private final IdentityManager identityManager;
private static final String PATH = "path";
@Autowired
- public RuleEngineService(KieContainer kieContainer, KeycloakAdminUtil keycloakAdminUtil) {
+ public RuleEngineService(KieContainer kieContainer, IdentityManager identityManager) {
this.kieContainer = kieContainer;
- this.keycloakAdminUtil = keycloakAdminUtil;
+ this.identityManager = identityManager;
}
public void doTransition(List stateContexts) {
StatelessKieSession kieSession = kieContainer.newStatelessKieSession();
- kieSession.setGlobal("keycloakAdminUtil", keycloakAdminUtil);
+ kieSession.setGlobal("identityManager", identityManager);
kieSession.setGlobal("ruleEngineService", this);
kieSession.execute(stateContexts);
}
public void doTransition(StateContext stateContext) {
StatelessKieSession kieSession = kieContainer.newStatelessKieSession();
- kieSession.setGlobal("keycloakAdminUtil", keycloakAdminUtil);
+ kieSession.setGlobal("identityManager", identityManager);
kieSession.setGlobal("ruleEngineService", this);
kieSession.execute(stateContext);
}
diff --git a/java/middleware/registry-middleware/workflow/src/main/resources/workflow/statetransitions.drl b/java/middleware/registry-middleware/workflow/src/main/resources/workflow/statetransitions.drl
index af42af88e..98a9237b6 100644
--- a/java/middleware/registry-middleware/workflow/src/main/resources/workflow/statetransitions.drl
+++ b/java/middleware/registry-middleware/workflow/src/main/resources/workflow/statetransitions.drl
@@ -1,9 +1,10 @@
package dev.sunbirdrc.workflow;
import dev.sunbirdrc.workflow.StateContext;
import dev.sunbirdrc.pojos.attestation.States;
+import dev.sunbirdrc.registry.identity_providers.pojos.CreateUserRequest;
dialect "mvel"
-global dev.sunbirdrc.keycloak.KeycloakAdminUtil keycloakAdminUtil;
+global dev.sunbirdrc.registry.identity_providers.pojos.IdentityManager identityManager;
global dev.sunbirdrc.workflow.RuleEngineService ruleEngineService;
rule "Set state as draft if there is a change"
@@ -40,9 +41,10 @@ rule "Create entity owner for newly added owner fields"
when
stateDefinition:StateContext(isOwnershipProperty() && isOwnerNewlyAdded() && isLoginEnabled());
then
- String owner = keycloakAdminUtil.createUser(stateDefinition.getEntityName(), stateDefinition.getUpdated().get("userId").textValue(),
- stateDefinition.getUpdated().get("email").textValue(), stateDefinition.getUpdated().get("mobile").textValue(),
- stateDefinition.getUpdated().get("password").textValue());
+ CreateUserRequest createUserRequest = new CreateUserRequest(stateDefinition.getEntityName(),
+ stateDefinition.getUpdated().get("userId").textValue(), stateDefinition.getUpdated().get("email").textValue(),
+ stateDefinition.getUpdated().get("mobile").textValue(), stateDefinition.getUpdated().get("password").textValue());
+ String owner = identityManager.createUser(createUserRequest);
stateDefinition.addOwner(owner);
end
@@ -58,4 +60,4 @@ rule "Revert if any modifications to system fields"
stateDefinition:StateContext(revertSystemFieldsChangedEnabled());
then
ruleEngineService.revertSystemFields(stateDefinition);
-end
\ No newline at end of file
+end
diff --git a/java/registry-interceptor/pom.xml b/java/registry-interceptor/pom.xml
index 2f4b97f1c..19b48a8f6 100644
--- a/java/registry-interceptor/pom.xml
+++ b/java/registry-interceptor/pom.xml
@@ -8,7 +8,6 @@
dev.sunbirdrc
2.0.3
- dev.sunbirdrc
registry-interceptor
2.0.3
jar
@@ -24,7 +23,7 @@
2.0.3
pom
import
-
+
@@ -48,7 +47,7 @@
pojos
2.0.3
-
+
org.springframework
spring-context
diff --git a/java/registry/pom.xml b/java/registry/pom.xml
index 3a1dc4b06..a7531967a 100644
--- a/java/registry/pom.xml
+++ b/java/registry/pom.xml
@@ -43,13 +43,7 @@
pom
import
-
- org.keycloak.bom
- keycloak-adapter-bom
- 11.0.2
- pom
- import
-
+
@@ -88,10 +82,6 @@
handlebars
4.3.1
-
- org.keycloak
- keycloak-spring-boot-starter
-
org.jboss.resteasy
resteasy-client
@@ -112,11 +102,7 @@
registry-interceptor
${revision}
-
- dev.sunbirdrc
- keycloak
- 2.0.3
-
+
dev.sunbirdrc
workflow
@@ -432,7 +418,26 @@
redis.clients
jedis
-
+
+ dev.sunbirdrc
+ identity-provider
+ 2.0.3
+
+
+ dev.sunbirdrc
+ keycloak
+ 2.0.3
+
+
+ dev.sunbirdrc
+ auth0
+ 2.0.3
+
+
+ dev.sunbirdrc
+ generic-iam
+ 2.0.3
+
@@ -481,6 +486,14 @@
org.springframework.boot
spring-boot-maven-plugin
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+
+
+
org.jacoco
@@ -565,4 +578,4 @@
-
\ No newline at end of file
+
diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/app/SunbirdRCApplication.java b/java/registry/src/main/java/dev/sunbirdrc/registry/app/SunbirdRCApplication.java
index bf28e1cb2..ecefd1d53 100644
--- a/java/registry/src/main/java/dev/sunbirdrc/registry/app/SunbirdRCApplication.java
+++ b/java/registry/src/main/java/dev/sunbirdrc/registry/app/SunbirdRCApplication.java
@@ -22,7 +22,7 @@
import java.time.Duration;
@SpringBootApplication(exclude={SecurityAutoConfiguration.class})
-@ComponentScan(basePackages = {"dev.sunbirdrc.registry", "dev.sunbirdrc.pojos", "dev.sunbirdrc.keycloak", "dev.sunbirdrc.workflow", "dev.sunbirdrc.plugin"})
+@ComponentScan(basePackages = {"dev.sunbirdrc.registry", "dev.sunbirdrc.pojos", "dev.sunbirdrc.auth", "dev.sunbirdrc.workflow", "dev.sunbirdrc.plugin"})
public class SunbirdRCApplication {
private static ApplicationContext context;
private static SpringApplication application = new SpringApplication(SunbirdRCApplication.class);
diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/config/GenericConfiguration.java b/java/registry/src/main/java/dev/sunbirdrc/registry/config/GenericConfiguration.java
index 10ffcec5e..fb48adcc5 100644
--- a/java/registry/src/main/java/dev/sunbirdrc/registry/config/GenericConfiguration.java
+++ b/java/registry/src/main/java/dev/sunbirdrc/registry/config/GenericConfiguration.java
@@ -11,9 +11,11 @@
import dev.sunbirdrc.pojos.AuditRecord;
import dev.sunbirdrc.pojos.Response;
import dev.sunbirdrc.pojos.SunbirdRCInstrumentation;
+import dev.sunbirdrc.registry.authorization.SchemaAuthFilter;
import dev.sunbirdrc.registry.exception.CustomException;
import dev.sunbirdrc.registry.exception.CustomExceptionHandler;
import dev.sunbirdrc.registry.frame.FrameContext;
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityProviderConfiguration;
import dev.sunbirdrc.registry.interceptor.RequestIdValidationInterceptor;
import dev.sunbirdrc.registry.interceptor.ValidationInterceptor;
import dev.sunbirdrc.registry.middleware.util.Constants;
@@ -58,13 +60,11 @@
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.resource.PathResourceResolver;
import org.sunbird.akka.core.SunbirdActorFactory;
+import dev.sunbirdrc.registry.identity_providers.pojos.IdentityManager;
+import dev.sunbirdrc.registry.identity_providers.providers.IdentityProvider;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.HashSet;
+import java.util.*;
import static dev.sunbirdrc.registry.Constants.ATTESTATION_POLICY;
@@ -157,6 +157,8 @@ public class GenericConfiguration implements WebMvcConfigurer {
private String scheme;
@Autowired
private DBConnectionInfoMgr dbConnectionInfoMgr;
+ @Autowired
+ private IdentityProviderConfiguration identityProviderConfiguration;
@Bean
public ObjectMapper objectMapper() {
@@ -258,6 +260,15 @@ public IValidate validationServiceImpl() throws IOException, CustomException {
return null;
}
+ @Bean
+ public SchemaAuthFilter schemaAuthFilter() {
+ SchemaAuthFilter schemaAuthFilter = new SchemaAuthFilter();
+ schemaAuthFilter.appendAnonymousInviteSchema(iDefinitionsManager.getEntitiesWithAnonymousInviteRoles());
+ schemaAuthFilter.appendAnonymousSchema(iDefinitionsManager.getEntitiesWithAnonymousManageRoles());
+ logger.info("Added anonymous schema to auth filters");
+ return schemaAuthFilter;
+ }
+
@Bean
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public AuditRecord auditRecord() {
@@ -360,6 +371,7 @@ public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(validationInterceptor()).addPathPatterns("/add").order(orderIdx++);
} catch (IOException | CustomException e) {
logger.error("Exception occurred while adding validation interceptor: {}", ExceptionUtils.getStackTrace(e));
+ throw new RuntimeException(e);
}
}
}
@@ -456,4 +468,15 @@ public RegistryService registryService() {
// IAuditService auditService = new AuditProviderFactory().getAuditService(auditFrameStore);
// return auditService;
// }
+
+ @Bean
+ public IdentityManager identityManager() {
+ ServiceLoader loader = ServiceLoader.load(IdentityProvider.class);
+ for (IdentityProvider provider : loader) {
+ if (identityProviderConfiguration.getProvider().equals(provider.getClass().getName())) {
+ return provider.createManager(identityProviderConfiguration);
+ }
+ }
+ throw new RuntimeException("Identity provider " + identityProviderConfiguration.getProvider() + " not found");
+ }
}
diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/config/SchemaFilter.java b/java/registry/src/main/java/dev/sunbirdrc/registry/config/SchemaFilter.java
index 459fdd58f..e69de29bb 100644
--- a/java/registry/src/main/java/dev/sunbirdrc/registry/config/SchemaFilter.java
+++ b/java/registry/src/main/java/dev/sunbirdrc/registry/config/SchemaFilter.java
@@ -1,39 +0,0 @@
-package dev.sunbirdrc.registry.config;
-
-import dev.sunbirdrc.registry.util.IDefinitionsManager;
-import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import javax.servlet.*;
-import javax.servlet.http.HttpServletRequest;
-import java.io.IOException;
-
-@Component
-public class SchemaFilter implements Filter {
- private static final Logger logger = LoggerFactory.getLogger(SchemaFilter.class);
- private static final String INVITE_URL_ENDPOINT = "/invite";
- @Autowired
- private IDefinitionsManager definitionsManager;
-
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
- HttpServletRequest request = (HttpServletRequest) servletRequest;
- try {
- if (request.getRequestURI().contains(INVITE_URL_ENDPOINT) &&
- definitionsManager.getEntitiesWithAnonymousInviteRoles().stream().anyMatch(request.getRequestURI()::contains)) {
- servletRequest.getRequestDispatcher(((HttpServletRequest) servletRequest).getServletPath()).forward(servletRequest, servletResponse);
- return;
- } else if (definitionsManager.getEntitiesWithAnonymousManageRoles().stream().anyMatch(request.getRequestURI()::contains)) {
- servletRequest.getRequestDispatcher(((HttpServletRequest) servletRequest).getServletPath()).forward(servletRequest, servletResponse);
- return;
- }
- filterChain.doFilter(servletRequest, servletResponse);
- } catch (Exception e) {
- logger.error("Exception while applying security filters: {}", ExceptionUtils.getStackTrace(e));
- throw e;
- }
- }
-}
diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/config/SecurityConfig.java b/java/registry/src/main/java/dev/sunbirdrc/registry/config/SecurityConfig.java
deleted file mode 100644
index a93880853..000000000
--- a/java/registry/src/main/java/dev/sunbirdrc/registry/config/SecurityConfig.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package dev.sunbirdrc.registry.config;
-
-import dev.sunbirdrc.registry.util.DefinitionsManager;
-import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
-import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
-import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
-import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
-import org.springframework.security.core.session.SessionRegistryImpl;
-import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
-import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
-import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
-
-@Configuration
-@EnableWebSecurity
-@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
-@ConditionalOnProperty(name = "authentication.enabled",havingValue = "true",matchIfMissing = false)
-public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
-
- @Value("${authentication.enabled:true}") boolean authenticationEnabled;
-
- @Autowired
- private SchemaFilter schemaFilter;
- @Autowired
- public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
-
- KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
- keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(
- new SimpleAuthorityMapper());
- auth.authenticationProvider(keycloakAuthenticationProvider);
- }
-
- @Bean
- public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
- return new KeycloakSpringBootConfigResolver();
- }
-
- @Bean
- @Override
- protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
- return new RegisterSessionAuthenticationStrategy(
- new SessionRegistryImpl());
- }
-
- //TODO: verify all paths
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- super.configure(http);
-
- HttpSecurity httpConfig = http.csrf().disable();
- if (authenticationEnabled) {
- httpConfig.authorizeRequests()
- .antMatchers("/**/invite", "/health", "/error",
- "/_schemas/**", "/**/templates/**", "/**/*.json", "/**/verify",
- "/swagger-ui", "/**/search", "/**/attestation/**",
- "/api/docs/swagger.json","/api/docs/*.json", "/plugin/**", "/swagger-ui.html")
- .permitAll()
- .and()
- .addFilterBefore(schemaFilter, WebAsyncManagerIntegrationFilter.class)
- .authorizeRequests()
- .anyRequest()
- .authenticated();
- } else {
- httpConfig.authorizeRequests()
- .anyRequest()
- .permitAll();
- }
- }
-}
diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryAttestationPolicyController.java b/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryAttestationPolicyController.java
index dc5741f6e..cbbb0ec3d 100644
--- a/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryAttestationPolicyController.java
+++ b/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryAttestationPolicyController.java
@@ -32,7 +32,7 @@ public ResponseEntity createAttestationPolicy(@PathVariable String entityName, @
List userEntities = registryHelper.getUserEntities(request);
if (createAttestationEntities.containsAll(userEntities) && definitionsManager.isValidEntityName(entityName) &&
!registryHelper.isAttestationPolicyNameAlreadyUsed(entityName, attestationPolicy.getName())) {
- String userId = registryHelper.getUserId(request, entityName);
+ String userId = registryHelper.getUserId(entityName);
attestationPolicy.setCreatedBy(userId);
logger.info("Creating attestation policy for entity: {} - {}", entityName, attestationPolicy);
attestationPolicy.setEntity(entityName);
@@ -55,7 +55,7 @@ public ResponseEntity getAttestationPolicies(@PathVariable String entityName, Ht
Response response = new Response(Response.API_ID.READ, "OK", responseParams);
try {
if (definitionsManager.isValidEntityName(entityName)) {
- String userId = registryHelper.getUserId(request, entityName);
+ String userId = registryHelper.getUserId(entityName);
List userEntities = registryHelper.getUserEntities(request);
if (userEntities.contains(entityName)) {
logger.info("Retrieving attestation policies for entity: {}", entityName);
@@ -83,7 +83,7 @@ public ResponseEntity updateAttestationPolicy(@PathVariable String entityName, @
Response response = new Response(Response.API_ID.UPDATE, "OK", responseParams);
try {
if (definitionsManager.isValidEntityName(entityName)) {
- String userId = registryHelper.getUserId(request, entityName);
+ String userId = registryHelper.getUserId(entityName);
final Optional attestationPolicyOptional = registryHelper.findAttestationPolicyById(userId, policyOSID);
if (attestationPolicyOptional.isPresent() && attestationPolicyOptional.get().getCreatedBy().equals(userId)) {
logger.info("Updating attestation policies id: {}", policyOSID);
@@ -106,7 +106,7 @@ public ResponseEntity updateAttestationPolicyStatus(@PathVariable String entityN
Response response = new Response(Response.API_ID.UPDATE, "OK", responseParams);
try {
if (definitionsManager.isValidEntityName(entityName)) {
- String userId = registryHelper.getUserId(request, entityName);
+ String userId = registryHelper.getUserId(entityName);
Optional attestationPolicyOptional = registryHelper.findAttestationPolicyById(userId, policyId);
if (attestationPolicyOptional.isPresent() && attestationPolicyOptional.get().getCreatedBy().equals(userId)) {
logger.info("Updating attestation policy status of id: {}", policyId);
@@ -131,7 +131,7 @@ public ResponseEntity deleteAttestationPolicy(@PathVariable String entityName, @
Response response = new Response(Response.API_ID.UPDATE, "OK", responseParams);
try {
if (definitionsManager.isValidEntityName(entityName)) {
- String userId = registryHelper.getUserId(request, entityName);
+ String userId = registryHelper.getUserId(entityName);
Optional attestationPolicyOptional = registryHelper.findAttestationPolicyById(userId, policyId);
if (attestationPolicyOptional.isPresent() && attestationPolicyOptional.get().getCreatedBy().equals(userId)) {
logger.info("Updating attestation policy status of id: {}", policyId);
diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryClaimsController.java b/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryClaimsController.java
index 6ccf8226b..3097bba48 100644
--- a/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryClaimsController.java
+++ b/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryClaimsController.java
@@ -28,8 +28,6 @@
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
-import static dev.sunbirdrc.registry.middleware.util.Constants.USER_ID;
-
@RestController
@ConditionalOnProperty(name = "claims.enabled", havingValue = "true")
public class RegistryClaimsController extends AbstractController{
@@ -92,7 +90,7 @@ public ResponseEntity