Skip to content

Commit

Permalink
feat: add logic regarding jti info store and check
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksandra-bel committed Mar 5, 2024
1 parent dae1954 commit 6809578
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
package org.eclipse.tractusx.managedidentitywallets.controller;

import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.JWTParser;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
Expand All @@ -31,17 +32,19 @@
import org.apache.commons.lang3.StringUtils;
import org.eclipse.tractusx.managedidentitywallets.apidocs.SecureTokenControllerApiDoc;
import org.eclipse.tractusx.managedidentitywallets.constant.StringPool;
import org.eclipse.tractusx.managedidentitywallets.dao.entity.Jti;
import org.eclipse.tractusx.managedidentitywallets.dao.repository.JtiRepository;
import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository;
import org.eclipse.tractusx.managedidentitywallets.domain.BusinessPartnerNumber;
import org.eclipse.tractusx.managedidentitywallets.domain.DID;
import org.eclipse.tractusx.managedidentitywallets.domain.IdpTokenResponse;
import org.eclipse.tractusx.managedidentitywallets.domain.StsTokenErrorResponse;
import org.eclipse.tractusx.managedidentitywallets.domain.StsTokenResponse;
import org.eclipse.tractusx.managedidentitywallets.dto.SecureTokenRequest;
import org.eclipse.tractusx.managedidentitywallets.exception.InvalidIdpTokenResponseException;
import org.eclipse.tractusx.managedidentitywallets.exception.InvalidSecureTokenRequestException;
import org.eclipse.tractusx.managedidentitywallets.exception.UnknownBusinessPartnerNumberException;
import org.eclipse.tractusx.managedidentitywallets.exception.UnsupportedGrantTypeException;
import org.eclipse.tractusx.managedidentitywallets.exception.InvalidIdpTokenResponseException;
import org.eclipse.tractusx.managedidentitywallets.interfaces.SecureTokenService;
import org.eclipse.tractusx.managedidentitywallets.service.IdpAuthorization;
import org.eclipse.tractusx.managedidentitywallets.validator.SecureTokenRequestValidator;
Expand All @@ -58,6 +61,8 @@
import java.util.Set;
import java.util.regex.Pattern;

import static org.eclipse.tractusx.managedidentitywallets.utils.TokenParsingUtils.getJtiAccessToken;

@RestController
@Slf4j
@RequiredArgsConstructor
Expand All @@ -70,6 +75,8 @@ public class SecureTokenController {

private final WalletRepository walletRepo;

private final JtiRepository jtiRepository;

@InitBinder
void initBinder(WebDataBinder webDataBinder) {
webDataBinder.addValidators(new SecureTokenRequestValidator());
Expand Down Expand Up @@ -114,11 +121,17 @@ public ResponseEntity<StsTokenResponse> token(
throw new InvalidSecureTokenRequestException("The provided data could not be used to create and sign a token.");
}

// store jti info in repository
JWTClaimsSet jwtClaimsSet = responseJwt.getJWTClaimsSet();
String jtiValue = getJtiAccessToken(jwtClaimsSet);
Jti jti = Jti.builder().jti(jtiValue).isUsedStatus(false).build();
jtiRepository.save(jti);

// create the response
log.debug("Preparing StsTokenResponse.");
StsTokenResponse response = StsTokenResponse.builder()
.token(responseJwt.serialize())
.expiresAt(responseJwt.getJWTClaimsSet().getExpirationTime().getTime())
.expiresAt(jwtClaimsSet.getExpirationTime().getTime())
.build();
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
Expand All @@ -37,6 +38,7 @@
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Jti extends MIWBaseEntity {

@Id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@
import org.eclipse.tractusx.managedidentitywallets.config.MIWSettings;
import org.eclipse.tractusx.managedidentitywallets.constant.StringPool;
import org.eclipse.tractusx.managedidentitywallets.dao.entity.HoldersCredential;
import org.eclipse.tractusx.managedidentitywallets.dao.entity.Jti;
import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet;
import org.eclipse.tractusx.managedidentitywallets.dao.repository.HoldersCredentialRepository;
import org.eclipse.tractusx.managedidentitywallets.dao.repository.JtiRepository;
import org.eclipse.tractusx.managedidentitywallets.exception.BadDataException;
import org.eclipse.tractusx.managedidentitywallets.exception.MissingVcTypesException;
import org.eclipse.tractusx.managedidentitywallets.exception.PermissionViolationException;
Expand Down Expand Up @@ -67,6 +69,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

import static org.eclipse.tractusx.managedidentitywallets.constant.StringPool.BLANK_SEPARATOR;
Expand All @@ -75,6 +78,7 @@
import static org.eclipse.tractusx.managedidentitywallets.constant.StringPool.UNDERSCORE;
import static org.eclipse.tractusx.managedidentitywallets.utils.TokenParsingUtils.getClaimsSet;
import static org.eclipse.tractusx.managedidentitywallets.utils.TokenParsingUtils.getScope;
import static org.eclipse.tractusx.managedidentitywallets.utils.TokenParsingUtils.getStringClaim;

/**
* The type Presentation service.
Expand All @@ -97,6 +101,8 @@ public class PresentationService extends BaseService<HoldersCredential, Long> {

private final DidDocumentResolverService didDocumentResolverService;

private final JtiRepository jtiRepository;

@Override
protected BaseRepository<HoldersCredential, Long> getRepository() {
return holdersCredentialRepository;
Expand Down Expand Up @@ -290,11 +296,14 @@ private boolean validateCredential(VerifiableCredential credential) {
}

public Map<String, Object> createVpWithRequiredScopes(SignedJWT innerJWT, boolean asJwt) {

JWTClaimsSet jwtClaimsSet = getClaimsSet(innerJWT);
Jti jti = getJtiRecord(jwtClaimsSet);

List<HoldersCredential> holdersCredentials = new ArrayList<>();
List<String> missingVCTypes = new ArrayList<>();
List<VerifiableCredential> verifiableCredentials = new ArrayList<>();

JWTClaimsSet jwtClaimsSet = getClaimsSet(innerJWT);
String scopeValue = getScope(jwtClaimsSet);
String[] scopes = scopeValue.split(BLANK_SEPARATOR);

Expand All @@ -319,8 +328,10 @@ public Map<String, Object> createVpWithRequiredScopes(SignedJWT innerJWT, boolea

holdersCredentials.forEach(c -> verifiableCredentials.add(c.getData()));

return buildVP(asJwt, jwtClaimsSet.getAudience().get(0), callerWallet.getBpn(),
Map<String, Object> vp = buildVP(asJwt, jwtClaimsSet.getAudience().get(0), callerWallet.getBpn(),
callerWallet, verifiableCredentials);
changeJtiStatus(jti);
return vp;
}

private void checkReadPermission(String permission) {
Expand All @@ -340,4 +351,21 @@ private String removeVersion(String vcType) {
String[] parts = vcType.split(UNDERSCORE);
return (parts.length > 1) ? parts[0] : vcType;
}

private Jti getJtiRecord(JWTClaimsSet jwtClaimsSet) {
String jtiValue = getStringClaim(jwtClaimsSet, "jti");
Jti jti = jtiRepository.getByJti(jtiValue);
if (Objects.isNull(jti)) {
throw new BadDataException("Jti record does not exist");
} else if (jti.isUsedStatus()) {
throw new BadDataException("The token was already used");
} else {
return jti;
}
}

private void changeJtiStatus(Jti jti) {
jti.setUsedStatus(true);
jtiRepository.save(jti);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.eclipse.tractusx.managedidentitywallets.exception.BadDataException;

import java.text.ParseException;
import java.util.Objects;
import java.util.Optional;

@UtilityClass
Expand All @@ -36,6 +37,7 @@ public class TokenParsingUtils {
public static final String PARSING_TOKEN_ERROR = "Could not parse jwt token";
public static final String SCOPE = "scope";
public static final String BEARER_ACCESS_SCOPE = "bearer_access_scope";
public static final String JTI = "jti";

public static JWTClaimsSet getClaimsSet(SignedJWT tokenParsed) {
try {
Expand All @@ -53,6 +55,14 @@ public static SignedJWT parseToken(String token) {
}
}

public static String getStringClaim(JWTClaimsSet claimsSet, String name) {
try {
return claimsSet.getStringClaim(name);
} catch (ParseException e) {
throw new BadDataException(PARSING_TOKEN_ERROR, e);
}
}

public static Optional<String> getAccessToken(JWTClaimsSet claims) {
try {
String accessTokenValue = claims.getStringClaim(ACCESS_TOKEN);
Expand Down Expand Up @@ -80,4 +90,12 @@ public static String getScope(JWTClaimsSet jwtClaimsSet) {
throw new BadDataException("Token does not contain scope claim");
}
}

public static String getJtiAccessToken(JWTClaimsSet jwtClaimsSet) {
Optional<String> token = getAccessToken(jwtClaimsSet);
String accessToken = Objects.requireNonNull(token.get());
SignedJWT accessTokenJwt = parseToken(accessToken);
JWTClaimsSet accessTokenClaimsSet = getClaimsSet(accessTokenJwt);
return getStringClaim(accessTokenClaimsSet, JTI);
}
}

0 comments on commit 6809578

Please sign in to comment.