
one.credify.sdk.impl.OidcServiceImpl Maven / Gradle / Ivy
package one.credify.sdk.impl;
import com.fasterxml.jackson.core.JsonProcessingException;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import one.credify.crypto.Encryption;
import one.credify.crypto.Jwt;
import one.credify.sdk.CredifyConfig;
import one.credify.sdk.OidcService;
import one.credify.sdk.dto.OidcOptions;
import one.credify.sdk.dto.OidcResponse;
import one.credify.sdk.dto.UserInfoRes;
import one.credify.sdk.mapper.UserInfoResMapper;
import one.credify.sdk.model.UserOidcInfo;
import one.credify.sdk.restapi.OidcCoreRest;
import one.credify.sdk.utils.Constants;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.*;
public class OidcServiceImpl implements OidcService {
private static final String COMMITMENT_KEY = "commitment";
private final CredifyConfig config;
private final OidcCoreRest oidcCoreClient;
public OidcServiceImpl(CredifyConfig config, OidcCoreRest oidcCoreClient) {
this.config = config;
this.oidcCoreClient = oidcCoreClient;
}
public OidcResponse initiateOidc(String consumerId, String redirectUrl, String[] scopes, OidcOptions options) throws JsonProcessingException {
String state = UUID.randomUUID().toString().replace("-", "");
String nonce = UUID.randomUUID().toString().replace("-", "");
List finalScopes = new ArrayList<>(Arrays.asList(scopes));
if (StringUtils.isNotEmpty(options.getOfferCode())) {
String offerScope = "offer:" + options.getOfferCode();
if (StringUtils.isNotEmpty(options.getPackageCode())) {
offerScope = offerScope + ":" + options.getPackageCode();
}
finalScopes.add(offerScope);
}
if (StringUtils.isNotEmpty(options.getProductCode())) {
String scope = "product:" + options.getProductCode();
if (StringUtils.isNotEmpty(options.getPackageCode())) {
scope = scope + ":" + options.getPackageCode();
}
finalScopes.add(scope);
}
if (StringUtils.isNotEmpty(options.getDopCode())) {
finalScopes.add("dop:" + options.getDopCode());
}
if (StringUtils.isNotEmpty(options.getOrderId())) {
finalScopes.add("bnpl_order:" + options.getOrderId());
}
String formattedScopes = StringUtils.join(finalScopes.toArray(), " ");
String requestToken = this.config.getSigning().generateRequestToken(consumerId, "", finalScopes, options.getOfferCode(), options.getPackageCode(), options.getDopCode());
Map params = new HashMap<>();
params.put("client_id", consumerId);
params.put("redirect_uri", redirectUrl);
params.put("scope", formattedScopes);
params.put("response_type", !options.getResponseType().equals("") ? options.getResponseType() : "code");
params.put("response_mode", !options.getResponseMode().equals("") ? options.getResponseMode() : "query");
params.put("state", !options.getState().equals("") ? options.getState() : state);
params.put("nonce", nonce);
params.put("request_token", requestToken);
if (StringUtils.isNotEmpty(options.getPhoneNumber())) {
params.put("phone_number", options.getPhoneNumber());
}
if (StringUtils.isNotEmpty(options.getCountryCode())) {
params.put("country_code", options.getCountryCode());
}
if (StringUtils.isNotEmpty(options.getEntityId())) {
params.put("entity_id", options.getEntityId());
}
if (StringUtils.isNotEmpty(options.getLocalId())) {
params.put("local_id", options.getLocalId());
}
String oidcCoreUrl = this.config.getOidcCoreUrl();
String q = params.entrySet().stream()
.map(p -> {
if (p == null) {
return null;
}
try {
return URLEncoder.encode(p.getKey(), "UTF-8") + "=" + URLEncoder.encode((String) p.getValue(), "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
})
.reduce((p1, p2) -> p1 + "&" + p2)
.orElse("")
.replace("+", "%20");
String url = oidcCoreUrl + "/oauth2/auth?" + q;
return new OidcResponse(url, null, state, nonce);
}
public UserOidcInfo getUserInfo(String accessToken, String privateKey) throws Exception {
Encryption encryption;
if (StringUtils.isNotEmpty(privateKey)) {
encryption = new Encryption();
encryption.importPrivateKey(privateKey);
} else {
encryption = config.getEncryption();
}
String authorization = "Bearer " + accessToken;
UserInfoRes userInfoRes = this.oidcCoreClient.getUserInfo(authorization).execute().body();
if (userInfoRes == null) {
return null;
}
Map customClaims = new HashMap<>();
Map customClaimCommitments = new HashMap<>();
UserOidcInfo.Commitment commitment = UserOidcInfo.Commitment.builder()
.customClaimCommitments(customClaimCommitments)
.build();
UserInfoRes.UserInfo userInfo = new UserInfoRes.UserInfo();
// parsing claim source jwe value
for (String scopeName : userInfoRes.getClaimSources().keySet()) {
UserInfoRes.ClaimSourceValue value = userInfoRes.getClaimSources().get(scopeName);
if (StringUtils.isEmpty(value.getJwt())) {
continue;
}
// parse jwe value
Jwt jwt = Jwt.parseJwe(encryption, value.getJwt());
// checking custom scope name
if (scopeName.split(Constants.CUSTOM_SCOPE_NAME_SPLIT).length > 1) {
for (String claimName : jwt.getPayload().keySet()) {
String[] claimParts = claimName.split(Constants.CUSTOM_SCOPE_NAME_SPLIT);
if (COMMITMENT_KEY.equals(claimParts[claimParts.length - 1])) {
customClaimCommitments.put(claimName, String.valueOf(jwt.getPayload().get(claimName)));
} else {
customClaims.put(claimName, String.valueOf(jwt.getPayload().get(claimName)));
}
}
}
// map json value and set user info by each specific scope name
switch (scopeName) {
case Constants.STANDARD_SCOPE_NAME_OPENID:
userInfo.setOpenid(Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.OpenidDto.class));
break;
case Constants.STANDARD_SCOPE_NAME_PROFILE:
userInfo.setProfile(Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.Profile.class));
commitment.setProfileCommitment(userInfo.getProfile().getProfileCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_ADVANCED_PROFILE:
userInfo.setAdvanceProfile(Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.AdvanceProfile.class));
commitment.setAdvancedProfileCommitment(userInfo.getAdvanceProfile().getAdvancedProfileCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_PHONE:
userInfo.setPhone(Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.Phone.class));
commitment.setPhoneCommitment(userInfo.getPhone().getPhoneCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_EMAIL:
userInfo.setEmail(Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.Email.class));
commitment.setEmailCommitment(userInfo.getEmail().getEmailCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_ADDRESS:
UserInfoRes.AddressDto addressDto = Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.AddressDto.class);
userInfo.setAddress(addressDto.getAddress());
commitment.setAddressCommitment(addressDto.getAddressCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_PERMANENT_ADDRESS:
UserInfoRes.PermanentAddressDto permanentAddressDto = Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.PermanentAddressDto.class);
userInfo.setPermanentAddress(permanentAddressDto.getPermanentAddress());
commitment.setPermanentAddressCommitment(permanentAddressDto.getPermanentAddressCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_EMPLOYMENT:
UserInfoRes.EmploymentDto employmentDto = Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.EmploymentDto.class);
userInfo.setEmployment(employmentDto.getEmployment());
commitment.setEmploymentCommitment(employmentDto.getEmploymentCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_INCOME:
userInfo.setIncome(Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.Income.class));
commitment.setIncomeCommitment(userInfo.getIncome().getIncomeCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_BANK_ACCOUNT:
UserInfoRes.BankAccountDto bankAccountDto = Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.BankAccountDto.class);
userInfo.setBankAccount(bankAccountDto.getBankAccount());
commitment.setBankAccountCommitment(bankAccountDto.getBankAccountCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_PRIMARY_REFERENCE_PERSON:
UserInfoRes.PrimaryReferencePersonDto primaryReferencePersonDto = Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.PrimaryReferencePersonDto.class);
userInfo.setPrimaryReferencePerson(primaryReferencePersonDto.getPrimaryReferencePerson());
commitment.setPrimaryReferencePersonCommitment(primaryReferencePersonDto.getPrimaryReferencePersonCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_SECONDARY_REFERENCE_PERSON:
UserInfoRes.SecondaryReferencePersonDto secondaryReferencePersonDto = Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.SecondaryReferencePersonDto.class);
userInfo.setSecondaryReferencePerson(secondaryReferencePersonDto.getSecondaryReferencePerson());
commitment.setSecondaryReferencePersonCommitment(secondaryReferencePersonDto.getSecondaryReferencePersonCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_SPOUSE:
UserInfoRes.SpouseDto spouseDto = Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.SpouseDto.class);
userInfo.setSpouse(spouseDto.getSpouse());
commitment.setSpouseCommitment(spouseDto.getSpouseCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_EKYC:
userInfo.setEkyc(Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.Ekyc.class));
commitment.setEkycCommitment(userInfo.getEkyc().getEkycCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_IDCARD:
userInfo.setIdcard(Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.Idcard.class));
commitment.setIdcardCommitment(userInfo.getIdcard().getIdcardCommitment());
break;
case Constants.STANDARD_SCOPE_NAME_DRIVING_PERMIT:
userInfo.setDrivingPermit(Constants.MAPPER.readValue(jwt.getRawPayload(), UserInfoRes.DrivingPermit.class));
commitment.setDrivingPermitCommitment(userInfo.getDrivingPermit().getDrivingPermitCommitment());
break;
}
}
// mapping decrypted user response to our standard user oidc info result
UserOidcInfo result = UserInfoResMapper.INSTANCE.fromResponse(userInfo);
result.setCredifyId(userInfoRes.getSub());
result.setCustomClaims(customClaims);
result.setCommitment(commitment);
// update ekyc info
if (userInfo.getIdcard() != null) {
result.getIdcard().updateEkycInfo(userInfo.getIdcard());
result.setIdcardOldNumber(userInfo.getIdcard().getIdcardOldNumber());
}
if (userInfo.getDrivingPermit() != null) {
result.getDrivingPermit().updateEkycInfo(userInfo.getDrivingPermit());
}
if (userInfo.getEkyc() != null) {
result.getEkyc().updateEkycInfo(userInfo.getEkyc());
}
return result;
}
@Override
public Map generateAccessToken(String consumerId, String code, String redirectUri) throws IOException, NoSuchAlgorithmException, SignatureException, InvalidKeyException {
String token = this.config.getSigning().generateJwt();
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("code", code)
.addFormDataPart("grant_type", "authorization_code")
.addFormDataPart("redirect_uri", redirectUri)
.addFormDataPart("client_secret", token)
.addFormDataPart("client_id", consumerId)
.addFormDataPart("client_type", "entity").build();
return this.oidcCoreClient.generateAccessToken(requestBody).execute().body();
}
private Object trimObject(Object obj) {
if (obj instanceof String) {
String objString = (String) obj;
return objString.replaceAll("\"", "");
}
if (obj instanceof Map) {
Map objMap = (Map) obj;
Map result = new HashMap<>();
objMap.forEach((key, value) -> {
result.put(key, trimObject(value));
});
return result;
}
return obj;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy