Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…-core into identity
  • Loading branch information
techsavvyash committed Jul 4, 2023
2 parents ce6ac5e + 97da68c commit f2d1bfd
Show file tree
Hide file tree
Showing 353 changed files with 20,053 additions and 2,978 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1 +1 @@
RELEASE_VERSION=v0.0.13
RELEASE_VERSION=v0.0.14
84 changes: 27 additions & 57 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
#SOURCES = $(wildcard java/**/*.java)
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
SOURCES := $(call rwildcard,java/,*.java)
RELEASE_VERSION = v0.0.13
RELEASE_VERSION = v0.0.14
IMAGES := dockerhub/sunbird-rc-core dockerhub/sunbird-rc-nginx dockerhub/sunbird-rc-context-proxy-service \
dockerhub/sunbird-rc-public-key-service dockerhub/sunbird-rc-keycloak dockerhub/sunbird-rc-certificate-api \
dockerhub/sunbird-rc-certificate-signer dockerhub/sunbird-rc-notification-service dockerhub/sunbird-rc-claim-ms \
dockerhub/sunbird-rc-digilocker-certificate-api dockerhub/sunbird-rc-bulk-issuance dockerhub/sunbird-rc-metrics \
dockerhub/sunbird-rc-identity-service

build: java/registry/target/registry.jar
echo ${SOURCES}
rm -rf java/claim/target/*.jar
Expand All @@ -13,6 +19,9 @@ build: java/registry/target/registry.jar
make -C deps/keycloak build
make -C services/public-key-service docker
make -C services/context-proxy-service docker
make -C services/metrics docker
make -C services/digilocker-certificate-api docker
make -C services/bulk_issuance docker
docker build -t dockerhub/sunbird-rc-nginx .
make -C services/identity-service/ docker

Expand All @@ -21,83 +30,44 @@ java/registry/target/registry.jar: $(SOURCES)
sh configure-dependencies.sh
cd java && ./mvnw clean install

test:
test: build
@echo "VIEW_DIR=java/apitest/src/test/resources/views" >> .env || echo "no permission to append to file"
@echo "SCHEMA_DIR=java/apitest/src/test/resources/schemas" >> .env || echo "no permission to append to file"
@docker-compose down
@rm -rf db-data* || echo "no permission to delete"
# test with ES & standard definition manager
@RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 DB_DIR=db-data-1 docker-compose up -d db es keycloak registry certificate-signer certificate-api
# test with distributed definition manager and native search
@SEARCH_PROVIDER_NAME=dev.sunbirdrc.registry.service.NativeSearchService RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 MANAGER_TYPE=DistributedDefinitionsManager DB_DIR=db-data-1 docker-compose up -d db keycloak registry certificate-signer certificate-api redis
@echo "Starting the test" && sh build/wait_for_port.sh 8080
@echo "Starting the test" && sh build/wait_for_port.sh 8081
@docker-compose ps
@curl -v http://localhost:8081/health
@cd java/apitest && ../mvnw -Pe2e test || echo 'Tests failed'
@docker-compose down
@rm -rf db-data-1 || echo "no permission to delete"
# test with distributed definition manager
@RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 MANAGER_TYPE=DistributedDefinitionsManager DB_DIR=db-data-2 docker-compose up -d db es keycloak registry certificate-signer certificate-api redis
@echo "Starting the test" && sh build/wait_for_port.sh 8080
@echo "Starting the test" && sh build/wait_for_port.sh 8081
@docker-compose ps
@curl -v http://localhost:8081/health
@cd java/apitest && ../mvnw -Pe2e test || echo 'Tests failed'
@docker-compose down
@rm -rf db-data-2 || echo "no permission to delete"
# test with native search service
@RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 DB_DIR=db-data-3 SEARCH_PROVIDER_NAME=dev.sunbirdrc.registry.service.NativeSearchService docker-compose up -d db keycloak registry certificate-signer certificate-api
@echo "Starting the test" && sh build/wait_for_port.sh 8080
@echo "Starting the test" && sh build/wait_for_port.sh 8081
@docker-compose ps
@curl -v http://localhost:8081/health
@cd java/apitest && ../mvnw -Pe2e test || echo 'Tests failed'
@docker-compose down
@rm -rf db-data-3 || echo "no permission to delete"
# test with kafka(async)
@ASYNC_ENABLED=true RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 DB_DIR=db-data-4 docker-compose up -d db es keycloak registry certificate-signer certificate-api kafka zookeeper
# test with kafka(async), events, notifications,
@NOTIFICATION_ENABLED=true NOTIFICATION_URL=http://notification-ms:8765/notification-service/v1/notification TRACK_NOTIFICATIONS=true EVENT_ENABLED=true ASYNC_ENABLED=true RELEASE_VERSION=latest KEYCLOAK_IMPORT_DIR=java/apitest/src/test/resources KEYCLOAK_SECRET=a52c5f4a-89fd-40b9-aea2-3f711f14c889 DB_DIR=db-data-2 docker-compose up -d db es keycloak registry certificate-signer certificate-api kafka zookeeper notification-ms metrics
@echo "Starting the test" && sh build/wait_for_port.sh 8080
@echo "Starting the test" && sh build/wait_for_port.sh 8081
@docker-compose ps
@curl -v http://localhost:8081/health
@cd java/apitest && MODE=async ../mvnw -Pe2e test || echo 'Tests failed'
@docker-compose down
@rm -rf db-data-4 || echo "no permission to delete"
@rm -rf db-data-2 || 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
make -C services/identity-service test
make -C services/bulk_issuance test
make -C services/identity-service test

clean:
@rm -rf target || true
@rm java/registry/target/registry.jar || true
release: test
docker tag dockerhub/sunbird-rc-core dockerhub/sunbird-rc-core:$(RELEASE_VERSION)
docker tag dockerhub/sunbird-rc-claim-ms dockerhub/sunbird-rc-claim-ms:$(RELEASE_VERSION)
docker tag dockerhub/sunbird-rc-notification-service dockerhub/sunbird-rc-notification-service:$(RELEASE_VERSION)
docker tag dockerhub/sunbird-rc-certificate-signer dockerhub/sunbird-rc-certificate-signer:$(RELEASE_VERSION)
docker tag dockerhub/sunbird-rc-certificate-api dockerhub/sunbird-rc-certificate-api:$(RELEASE_VERSION)
docker tag dockerhub/sunbird-rc-keycloak dockerhub/sunbird-rc-keycloak:$(RELEASE_VERSION)
docker tag dockerhub/sunbird-rc-public-key-service dockerhub/sunbird-rc-public-key-service:$(RELEASE_VERSION)
docker tag dockerhub/sunbird-rc-context-proxy-service dockerhub/sunbird-rc-context-proxy-service:$(RELEASE_VERSION)
docker tag dockerhub/sunbird-rc-nginx dockerhub/sunbird-rc-nginx:$(RELEASE_VERSION)
docker tag dockerhub/sunbird-rc-identity-service dockerhub/sunbird-rc-identity-service:$(RELEASE_VERSION)
docker push dockerhub/sunbird-rc-core:latest
docker push dockerhub/sunbird-rc-core:$(RELEASE_VERSION)
docker push dockerhub/sunbird-rc-claim-ms:latest
docker push dockerhub/sunbird-rc-claim-ms:$(RELEASE_VERSION)
docker push dockerhub/sunbird-rc-notification-service:latest
docker push dockerhub/sunbird-rc-notification-service:$(RELEASE_VERSION)
docker push dockerhub/sunbird-rc-certificate-signer:latest
docker push dockerhub/sunbird-rc-certificate-signer:$(RELEASE_VERSION)
docker push dockerhub/sunbird-rc-certificate-api:latest
docker push dockerhub/sunbird-rc-certificate-api:$(RELEASE_VERSION)
docker push dockerhub/sunbird-rc-keycloak:latest
docker push dockerhub/sunbird-rc-keycloak:$(RELEASE_VERSION)
docker push dockerhub/sunbird-rc-public-key-service:latest
docker push dockerhub/sunbird-rc-public-key-service:$(RELEASE_VERSION)
docker push dockerhub/sunbird-rc-context-proxy-service:latest
docker push dockerhub/sunbird-rc-context-proxy-service:$(RELEASE_VERSION)
docker push dockerhub/sunbird-rc-nginx:latest
docker push dockerhub/sunbird-rc-nginx:$(RELEASE_VERSION)
docker push dockerhub/sunbird-rc-identity-service:$(RELEASE_VERSION)
for image in $(IMAGES); \
do \
echo $$image; \
docker tag $$image:latest $$image:$(RELEASE_VERSION);\
docker push $$image:latest;\
docker push $$image:$(RELEASE_VERSION);\
done
@cd tools/cli/ && npm publish


89 changes: 52 additions & 37 deletions api-documentation/issue-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ tags:
- name: Verifying
description: The following APIs are defined for verifying a Verifiable Credential
paths:
/credentials/claim:
/credentials/issue:
post:
tags:
- Issuing
Expand All @@ -46,40 +46,6 @@ paths:
description: error
content: {}
x-codegen-request-body-name: body
/credentials/sign:
post:
tags:
- Issuing
summary: Credential sign API
operationId: credentialSign
requestBody:
description: Credential payload
content:
'appliation/json':
schema:
allOf:
- type: object
properties:
credentialId:
type: string
example: credentialDID
description: Optional field, required if a claim is already made
- $ref: '#/components/schemas/credentialRequest'
required: true
responses:
201:
description: Credential successfully issued!
content:
'application/json':
schema:
$ref: '#/components/schemas/credentialResponse'
400:
description: Invalid Input
content: {}
500:
description: error
content: {}
x-codegen-request-body-name: body
/credentials/{id}:
get:
tags:
Expand Down Expand Up @@ -115,7 +81,7 @@ paths:
content:
'appliation/json':
schema:
$ref: '#/components/schemas/verifiableCredentialType'
$ref: '#/components/schemas/verifiableCredential'
401:
description: Not Authorized
content: {}
Expand Down Expand Up @@ -187,7 +153,7 @@ paths:
schema:
type: array
items:
$ref: '#/components/schemas/verifiableCredentialType'
$ref: '#/components/schemas/verifiableCredential'
401:
description: Not Authorized
content: {}
Expand Down Expand Up @@ -376,6 +342,55 @@ components:
credentialSubject:
type: object
properties: {}

verifiableCredential:
type: object
properties:
context:
type: array
items:
type: string
id:
type: string
type:
type: string
issuer:
type: object
properties: {}
issuanceDate:
type: string
format: date-time
expirationDate:
type: string
format: date-time
credentialSubject:
type: object
properties: {}
proof:
type: object
properties:
type:
type: string
created:
type: string
format: 'date-time'
challenge:
type: string
domain:
type: string
nonce:
type: string
verificationMethod:
type: string
proofPurpose:
type: string
jws:
type: string
proofValue:
type: string




securitySchemes:
Authorization:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package in.divoc.api.authenticator;

public interface IValidation {
boolean validate(String mobileNumber);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.ErrorRepresentation;

import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
Expand All @@ -22,13 +25,16 @@ public class MobileNumberAuthenticator extends AbstractUsernameFormAuthenticator
private final OTPService mockOTPService;
private final OTPService otpService;
private final NotifyService notifyService;
private final IValidation iValidation;


private static final String mockOtp = System.getenv().getOrDefault("MOCK_OTP", "true");

public MobileNumberAuthenticator() {
this.mockOTPService = new MockOTPServiceImpl();
this.otpService = new OTPServiceImpl();
this.notifyService = new NotifyService();
this.iValidation = new ValidationService();
}

@Override
Expand All @@ -39,39 +45,93 @@ public void action(AuthenticationFlowContext context) {
System.err.println("action request " + type);
if (type.equals(LOGIN_FORM)) {
//TODO: rename form id
String INVALID_REGISTRATION = "INVALID_REGISTRATION";
String INVALID_USERNAME = "INVALID_USERNAME";
String mobileNumber = formData.getFirst(MOBILE_NUMBER);
List<UserModel> users = context.getSession().users()
.searchForUserByUserAttributeStream(context.getSession().getContext().getRealm(), MOBILE_NUMBER, mobileNumber).collect(Collectors.toList());
if (users.size() > 0) {
generateOTPAndNotify(context, mobileNumber, users);
} else {
users = context.getSession().users()
.searchForUserByUserAttributeStream(context.getSession().getContext().getRealm(), EMAIL, mobileNumber).collect(Collectors.toList());
if(iValidation.validate(mobileNumber)) {
List<UserModel> users = context.getSession().users()
.searchForUserByUserAttributeStream(context.getSession().getContext().getRealm(), MOBILE_NUMBER, mobileNumber).collect(Collectors.toList());
if (users.size() > 0) {
if (checkIfMaxResendOtpLimitReached(context)) return;
generateOTPAndNotify(context, mobileNumber, users);
} else {
context.failure(AuthenticationFlowError.INVALID_USER);
users = context.getSession().users()
.searchForUserByUserAttributeStream(context.getSession().getContext().getRealm(), EMAIL, mobileNumber).collect(Collectors.toList());
if (users.size() > 0) {
generateOTPAndNotify(context, mobileNumber, users);
} else {
Response response = context.form().setError(System.getenv().getOrDefault(INVALID_REGISTRATION, "No user found with this username")).createForm(MOBILE_LOGIN_UI);
context.failure(AuthenticationFlowError.INVALID_USER, response);
}
}
}
else {
Response response = context.form().setError(System.getenv().getOrDefault(INVALID_USERNAME, "Please enter correct Username")).createForm(MOBILE_LOGIN_UI);
context.failure(AuthenticationFlowError.INVALID_USER, response);
}
} else if (type.equals(VERIFY_OTP_FORM)) {
String sessionKey = context.getAuthenticationSession().getAuthNote(OTP);
if (sessionKey != null) {
String secret = formData.getFirst(OTP);
String VALID_OTP = "VALID_OTP";
if (secret != null) {
if (secret.equals(sessionKey)) {
context.success();
} else {
context.failure(AuthenticationFlowError.INVALID_CREDENTIALS);
Response response = context.form().setError(System.getenv().getOrDefault(VALID_OTP, "Please enter correct OTP")).createForm(VERIFY_OTP_UI);
if(checkIfMaxOtpTriesReached(context)) {
return;
}
context.failure(AuthenticationFlowError.INVALID_CREDENTIALS, response);
}
} else {
context.failure(AuthenticationFlowError.INVALID_CREDENTIALS);
Response response = context.form().setError(System.getenv().getOrDefault(VALID_OTP, "Please enter correct OTP")).createForm(VERIFY_OTP_UI);
if(checkIfMaxOtpTriesReached(context)) {
return;
}
context.failure(AuthenticationFlowError.INVALID_CREDENTIALS, response);
}
} else {
context.challenge(context.form().createForm(MOBILE_LOGIN_UI));
}
}
}

private static boolean checkIfMaxResendOtpLimitReached(AuthenticationFlowContext context) {
String MAX_RESEND_TRIES = "MAX_RESEND_TRIES";
String RESEND_OTP_TRY_COUNT = "RESEND_OTP_TRY_COUNT";
String resendTries = context.getAuthenticationSession().getAuthNote(RESEND_OTP_TRY_COUNT);
System.out.println("RESEND RETRIES : " + resendTries);
int count = resendTries == null ? 0 : Integer.parseInt(resendTries);
count++;
if(count == Integer.parseInt(System.getenv().getOrDefault(MAX_RESEND_TRIES, "3")) + 1) {
context.getAuthenticationSession().setAuthNote(RESEND_OTP_TRY_COUNT, null);
context.failure(AuthenticationFlowError.INTERNAL_ERROR);
return true;
}
context.getAuthenticationSession().setAuthNote(RESEND_OTP_TRY_COUNT, count + "" );
return false;
}

private boolean checkIfMaxOtpTriesReached(AuthenticationFlowContext context) {
String OTP_TRIES = "OTP_TRIES";
String OTP_MAX_RETRY_LIMIT = "OTP_MAX_RETRY_LIMIT";
String otpTries = context.getAuthenticationSession().getAuthNote(OTP_TRIES);
System.out.println("OTP TRIES : " + otpTries);
int count = (otpTries == null ? 0 : Integer.parseInt(otpTries));
count++;
int maxLimit = Integer.parseInt(System.getenv().getOrDefault(OTP_MAX_RETRY_LIMIT, "3"));
if(count == maxLimit) {
context.getAuthenticationSession().setAuthNote(OTP_TRIES, null);
String MAX_RETRIES_LIMIT_MESSAGE = "MAX_RETRIES_LIMIT_MESSAGE";
Response response = context.form().setError(System.getenv().getOrDefault(MAX_RETRIES_LIMIT_MESSAGE, "Max failed login limit reached")).createForm(MOBILE_LOGIN_UI);
context.failure(AuthenticationFlowError.INVALID_CREDENTIALS, response);
return true;
}
context.getAuthenticationSession().setAuthNote(OTP_TRIES, "" + count);
return false;
}

private void generateOTPAndNotify(AuthenticationFlowContext context, String mobileNumber, List<UserModel> users) {
UserModel user = users.get(0);
String otp;
Expand Down
Loading

0 comments on commit f2d1bfd

Please sign in to comment.