Skip to content

Commit

Permalink
Prevent using studielink in remote-creation API
Browse files Browse the repository at this point in the history
  • Loading branch information
oharsta committed Jun 5, 2024
1 parent b7c001f commit 6ad9393
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 53 deletions.
1 change: 0 additions & 1 deletion myconext-server/src/main/java/myconext/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import lombok.Setter;
import myconext.exceptions.WeakPasswordException;
import myconext.manage.Manage;
import myconext.remotecreation.StudieLinkEduID;
import myconext.tiqr.SURFSecureID;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
@AllArgsConstructor
@Getter
@Setter
public class StudieLinkEduID implements Serializable {
public class ExternalEduID implements Serializable {

@NotNull
private String email;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,36 +131,37 @@ public ResponseEntity<EduIDValue> eduIDForInstitution(@Parameter(hidden = true)
description = "Create an eduID",
responses = {
@ApiResponse(responseCode = "201", description = "Created",
content = {@Content(schema = @Schema(implementation = StudieLinkEduID.class))}),
content = {@Content(schema = @Schema(implementation = ExternalEduID.class))}),
@ApiResponse(responseCode = "400", description = "BadRequest",
content = {@Content(schema = @Schema(implementation = StatusResponse.class),
examples = {@ExampleObject(value = "{\"status\":400}")})}),
@ApiResponse(responseCode = "409", description = "Conflict - email already exists",
content = {@Content(schema = @Schema(implementation = StatusResponse.class),
examples = {@ExampleObject(value = "{\"status\":409}")})})})
public ResponseEntity<StudieLinkEduID> createEduID(@Parameter(hidden = true) @AuthenticationPrincipal RemoteUser remoteUser,
@RequestBody @Validated StudieLinkEduID studieLinkEduID) {
String email = studieLinkEduID.getEmail();
public ResponseEntity<ExternalEduID> createEduID(@Parameter(hidden = true) @AuthenticationPrincipal RemoteUser remoteUser,
@RequestBody @Validated ExternalEduID externalEduID) {
String email = externalEduID.getEmail();
LOG.debug(String.format("eduid-create by %s for %s", remoteUser.getUsername(), email));

userRepository.findUserByEmail(email).ifPresent(u -> {
throw new DuplicateUserEmailException();
});
IdentityProvider identityProvider = new IdentityProvider(null, studieLinkEduID.getBrinCode(), remoteUser.getInstitutionGUID(),
IdpScoping.studielink.name(), IdpScoping.studielink.name(),
String apiUserName = remoteUser.getUsername();
IdentityProvider identityProvider = new IdentityProvider(null, externalEduID.getBrinCode(), remoteUser.getInstitutionGUID(),
apiUserName, apiUserName,
String.format("https://static.surfconext.nl/logos/org/%s.png", remoteUser.getInstitutionGUID()));
User user = new User(UUID.randomUUID().toString(), studieLinkEduID.getEmail(), studieLinkEduID.getChosenName(),
studieLinkEduID.getFirstName(), studieLinkEduID.getLastName(), remoteUser.getSchacHome(), LocaleContextHolder.getLocale().getLanguage(),
User user = new User(UUID.randomUUID().toString(), externalEduID.getEmail(), externalEduID.getChosenName(),
externalEduID.getFirstName(), externalEduID.getLastName(), remoteUser.getSchacHome(), LocaleContextHolder.getLocale().getLanguage(),
identityProvider, manage);

String eduIDValue = user.getEduIDS().get(0).getValue();
studieLinkEduID.setEduIDValue(eduIDValue);
ExternalLinkedAccount externalLinkedAccount = attributeMapper.externalLinkedAccountFromStudieLink(studieLinkEduID);
externalEduID.setEduIDValue(eduIDValue);
ExternalLinkedAccount externalLinkedAccount = attributeMapper.createExternalLinkedAccount(externalEduID, IdpScoping.valueOf(apiUserName));
user.getExternalLinkedAccounts().add(externalLinkedAccount);

userRepository.save(user);

return ResponseEntity.ok(studieLinkEduID);
return ResponseEntity.ok(externalEduID);
}

@PutMapping(value = {"/eduid-update"})
Expand All @@ -169,30 +170,30 @@ public ResponseEntity<StudieLinkEduID> createEduID(@Parameter(hidden = true) @Au
description = "Update an eduID",
responses = {
@ApiResponse(responseCode = "201", description = "Created",
content = {@Content(schema = @Schema(implementation = StudieLinkEduID.class))}),
content = {@Content(schema = @Schema(implementation = ExternalEduID.class))}),
@ApiResponse(responseCode = "400", description = "BadRequest",
content = {@Content(schema = @Schema(implementation = StatusResponse.class),
examples = {@ExampleObject(value = "{\"status\":400}")})})})
public ResponseEntity<StudieLinkEduID> updateEduID(@Parameter(hidden = true) @AuthenticationPrincipal RemoteUser remoteUser,
@RequestBody @Validated StudieLinkEduID studieLinkEduID) {
LOG.debug(String.format("eduid-update by %s for %s", remoteUser.getUsername(), studieLinkEduID.getEmail()));
public ResponseEntity<ExternalEduID> updateEduID(@Parameter(hidden = true) @AuthenticationPrincipal RemoteUser remoteUser,
@RequestBody @Validated ExternalEduID externalEduID) {
LOG.debug(String.format("eduid-update by %s for %s", remoteUser.getUsername(), externalEduID.getEmail()));

String eduIDValue = studieLinkEduID.getEduIDValue();
String eduIDValue = externalEduID.getEduIDValue();
User user = userRepository.findByEduIDS_value(eduIDValue)
.orElseThrow(() -> new UserNotFoundException(String.format("User not found by eduID %s", eduIDValue)));
//Not all attributes can be changed
user.setGivenName(studieLinkEduID.getFirstName());
user.setFamilyName(studieLinkEduID.getLastName());
user.setGivenName(externalEduID.getFirstName());
user.setFamilyName(externalEduID.getLastName());
ExternalLinkedAccount externalLinkedAccount = user.getExternalLinkedAccounts().stream()
.filter(account -> IdpScoping.studielink.equals(account.getIdpScoping()))
.filter(account -> IdpScoping.valueOf(remoteUser.getUsername()).equals(account.getIdpScoping()))
.findAny()
.orElseThrow(() -> new ResourceGoneException(String.format("User %s has removed the studie link link", user.getEmail())));
//Not all external attributes can be changed
externalLinkedAccount.setVerification(studieLinkEduID.getVerification());
externalLinkedAccount.setBrinCode(studieLinkEduID.getBrinCode());
externalLinkedAccount.setVerification(externalEduID.getVerification());
externalLinkedAccount.setBrinCode(externalEduID.getBrinCode());

userRepository.save(user);

return ResponseEntity.ok(studieLinkEduID);
return ResponseEntity.ok(externalEduID);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import myconext.model.ExternalLinkedAccount;
import myconext.model.IdpScoping;
import myconext.model.VerifyIssuer;
import myconext.remotecreation.StudieLinkEduID;
import myconext.remotecreation.ExternalEduID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
Expand Down Expand Up @@ -145,14 +145,14 @@ public ExternalLinkedAccount externalLinkedAccountFromAttributes(
throw new IllegalArgumentException();
}

public ExternalLinkedAccount externalLinkedAccountFromStudieLink(StudieLinkEduID eduID) {
public ExternalLinkedAccount createExternalLinkedAccount(ExternalEduID eduID, IdpScoping idpScoping) {
return new ExternalLinkedAccount(
//String subjectId
eduID.getIdentifier(),
//IdpScoping idpScoping
IdpScoping.studielink,
idpScoping,
//VerifyIssuer issuer
new VerifyIssuer(IdpScoping.studielink.name(), IdpScoping.studielink.name()),
new VerifyIssuer(idpScoping.name(), idpScoping.name()),
//Verification
eduID.getVerification(),
//String serviceUUID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ void eduIDForInstitutionBrinCodeNotExists() {

@Test
void createEduIDHappyFlow() {
StudieLinkEduID studieLinkEduID = new StudieLinkEduID(
ExternalEduID externalEduID = new ExternalEduID(
"[email protected]",
null,
"Mary",
Expand All @@ -145,15 +145,15 @@ void createEduIDHappyFlow() {
Verification.Decentraal,
null
);
StudieLinkEduID studieLinkEduIdResult = given()
ExternalEduID externalEduIDResult = given()
.when()
.auth().preemptive().basic(userName, password)
.contentType(ContentType.JSON)
.body(studieLinkEduID)
.body(externalEduID)
.post("/api/remote-creation/eduid-create")
.as(new TypeRef<>() {
});
String eduIDValue = studieLinkEduIdResult.getEduIDValue();
String eduIDValue = externalEduIDResult.getEduIDValue();
User user = userRepository.findByEduIDS_value(eduIDValue).get();
EduID newEduID = user.getEduIDS().stream()
.filter(anEduID -> anEduID.getValue().equals(eduIDValue))
Expand All @@ -169,7 +169,7 @@ void createEduIDHappyFlow() {

@Test
void createEduIDConflict() {
StudieLinkEduID studieLinkEduID = new StudieLinkEduID(
ExternalEduID externalEduID = new ExternalEduID(
email,
null,
"Mary",
Expand All @@ -185,15 +185,15 @@ void createEduIDConflict() {
.when()
.auth().preemptive().basic(userName, password)
.contentType(ContentType.JSON)
.body(studieLinkEduID)
.body(externalEduID)
.post("/api/remote-creation/eduid-create")
.then()
.statusCode(HttpStatus.CONFLICT.value());
}

@Test
void createEduIDBadRequest() {
StudieLinkEduID studieLinkEduID = new StudieLinkEduID(
ExternalEduID externalEduID = new ExternalEduID(
null,
null,
"Mary",
Expand All @@ -209,15 +209,15 @@ void createEduIDBadRequest() {
.when()
.auth().preemptive().basic(userName, password)
.contentType(ContentType.JSON)
.body(studieLinkEduID)
.body(externalEduID)
.post("/api/remote-creation/eduid-create")
.then()
.statusCode(HttpStatus.BAD_REQUEST.value());
}

@Test
void updateEduIDHappyFlow() {
StudieLinkEduID studieLinkEduID = new StudieLinkEduID(
ExternalEduID externalEduID = new ExternalEduID(
"[email protected]",
null,
"Mary",
Expand All @@ -229,33 +229,33 @@ void updateEduIDHappyFlow() {
Verification.Decentraal,
null
);
StudieLinkEduID studieLinkEduIdResult = given()
ExternalEduID externaalEduIDResult = given()
.when()
.auth().preemptive().basic(userName, password)
.contentType(ContentType.JSON)
.body(studieLinkEduID)
.body(externalEduID)
.post("/api/remote-creation/eduid-create")
.as(new TypeRef<>() {
});
studieLinkEduIdResult.setBrinCode("QWER");
externaalEduIDResult.setBrinCode("QWER");
given()
.when()
.auth().preemptive().basic(userName, password)
.contentType(ContentType.JSON)
.body(studieLinkEduIdResult)
.body(externaalEduIDResult)
.put("/api/remote-creation/eduid-update")
.as(new TypeRef<>() {
});
String eduIDValue = studieLinkEduIdResult.getEduIDValue();
String eduIDValue = externaalEduIDResult.getEduIDValue();
User user = userRepository.findByEduIDS_value(eduIDValue).get();

assertEquals(1, user.getExternalLinkedAccounts().size());
assertEquals(studieLinkEduIdResult.getBrinCode(), user.getExternalLinkedAccounts().get(0).getBrinCode());
assertEquals(externaalEduIDResult.getBrinCode(), user.getExternalLinkedAccounts().get(0).getBrinCode());
}

@Test
void updateEduIDNotFound() {
StudieLinkEduID studieLinkEduID = new StudieLinkEduID(
ExternalEduID externalEduID = new ExternalEduID(
"[email protected]",
null,
"Mary",
Expand All @@ -267,28 +267,28 @@ void updateEduIDNotFound() {
Verification.Decentraal,
null
);
StudieLinkEduID studieLinkEduIdResult = given()
ExternalEduID externalEduIDResult = given()
.when()
.auth().preemptive().basic(userName, password)
.contentType(ContentType.JSON)
.body(studieLinkEduID)
.body(externalEduID)
.post("/api/remote-creation/eduid-create")
.as(new TypeRef<>() {
});
studieLinkEduIdResult.setEduIDValue(UUID.randomUUID().toString());
externalEduIDResult.setEduIDValue(UUID.randomUUID().toString());
given()
.when()
.auth().preemptive().basic(userName, password)
.contentType(ContentType.JSON)
.body(studieLinkEduIdResult)
.body(externalEduIDResult)
.put("/api/remote-creation/eduid-update")
.then()
.statusCode(HttpStatus.NOT_FOUND.value());
}

@Test
void updateEduIDExternalAccountGone() {
StudieLinkEduID studieLinkEduID = new StudieLinkEduID(
ExternalEduID externalEduID = new ExternalEduID(
"[email protected]",
null,
"Mary",
Expand All @@ -300,16 +300,16 @@ void updateEduIDExternalAccountGone() {
Verification.Decentraal,
null
);
StudieLinkEduID studieLinkEduIdResult = given()
ExternalEduID externalEduIDResult = given()
.when()
.auth().preemptive().basic(userName, password)
.contentType(ContentType.JSON)
.body(studieLinkEduID)
.body(externalEduID)
.post("/api/remote-creation/eduid-create")
.as(new TypeRef<>() {
});
//Now delete the externalAccount
String eduIDValue = studieLinkEduIdResult.getEduIDValue();
String eduIDValue = externalEduIDResult.getEduIDValue();
User user = userRepository.findByEduIDS_value(eduIDValue).get();
user.getExternalLinkedAccounts().clear();
userRepository.save(user);
Expand All @@ -318,7 +318,7 @@ void updateEduIDExternalAccountGone() {
.when()
.auth().preemptive().basic(userName, password)
.contentType(ContentType.JSON)
.body(studieLinkEduIdResult)
.body(externalEduIDResult)
.put("/api/remote-creation/eduid-update")
.then()
.statusCode(HttpStatus.GONE.value());
Expand Down

0 comments on commit 6ad9393

Please sign in to comment.