diff --git a/README.md b/README.md
index c58c8ab9..87560a3a 100644
--- a/README.md
+++ b/README.md
@@ -129,3 +129,8 @@ The redirect URI's for local development have to start with https. You can use t
```
ngrok http --domain okke.harsta.eu.ngrok.io 8081
```
+
+### Running the IdP and testing localhost
+
+The [idp_metadata.xml](idp_metadata.xml) file contains the IdP metadata for localhost development. Import an IdP in Manage and
+whitelist this for the SP's you want to test with. The OIDC-Playground is capable of testing the different ACR options.
\ No newline at end of file
diff --git a/idp_metadata.xml b/idp_metadata.xml
new file mode 100644
index 00000000..486a3e4f
--- /dev/null
+++ b/idp_metadata.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ MIICvDCCAaQCCQCOtlEewzza9zANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQKDBVPcmdhbml6YXRpb24sIENOPU9JREMwHhcNMjIwMTI3MTA0OTQ2WhcNMjMwMTI3MTA0OTQ2WjAgMR4wHAYDVQQKDBVPcmdhbml6YXRpb24sIENOPU9JREMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMf3M9YNm1B+Db2W+04fvY9nOOM4UU8A1mQkY3m6JGwyq2Hul3LGqEJQgXwtpJhA/TOnlMQ4je9h0/vDfyT7v0exEWhykOqOPcuZ4OVmSACtUiao3VE2HiZz7kjSsSvix0+UeaouqxDcGpi4+qIrPFHFqQ8rNdl+2S4ZEzGQxqgK6n92a9Ng+mnSx21FEIu3o8rNqlTrN9mhtfoTSiVUDIWEM/1fAwt7NOzpw7GMbnV8nbSFUtEnn0oNm8H0Qqy8BAhMUHL8AZXO5Uwm+cVmVh9JQtWANfzhPD7l+DD8h7W5fi1VeLiAgo0Go0EF6z1Jk2aGTKWBQzODClF01j5NizAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAA8ttJeHPAMHduvwmvzkMjw2p0w7AptQXcqTlgBP3MAZKncn81SkO0jd0gvBTmUzt4oMiRJYnTm1ghUXNW5qK+2fjXwt5HXXz5OJGrN6A0MybOd/OXK/3Q5PHWvfLE/+zLWT67c34n0q6KDBBZheoF2SKw10s/mDJ1eHRHZIlsFmF6Z3Ll6h3fkL/0MsBOkmQ3CEtpTFpNk9lma3cnGQJ7p7t4T9iVNDSL1/fqDZPoaVzUJx39sXjb/ouCIDrXN3+ayElehQa+aXpE4KdG22j4Dm+k83OO3hujjugEAze+CeHDyy7X9c6c79bCXBU4HQK0ff0PiSxv0xpjsP3tMMr1U=
+
+
+
+ urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
+
+
+
+ Support
+ OpenConext
+ mailto:support@openconext.org
+
+
+ Support
+ OpenConext
+ mailto:technical@openconext.org
+
+
+ Support
+ OpenConext
+ mailto:administrative@openconext.org
+
+
\ No newline at end of file
diff --git a/myconext-server/src/main/java/myconext/api/UserController.java b/myconext-server/src/main/java/myconext/api/UserController.java
index e5692589..efa4ba5a 100644
--- a/myconext-server/src/main/java/myconext/api/UserController.java
+++ b/myconext-server/src/main/java/myconext/api/UserController.java
@@ -100,6 +100,7 @@ public class UserController implements UserAuthentication {
private final List issuers;
//For now, hardcode the not known issuers from test
private final List unknownIssuers = List.of("CURRNL2A");
+ private final int nudgeAppDays;
public UserController(UserRepository userRepository,
UserCredentialRepository userCredentialRepository,
@@ -123,6 +124,7 @@ public UserController(UserRepository userRepository,
@Value("${rp_id}") String rpId,
@Value("${feature.default_remember_me}") boolean featureDefaultRememberMe,
@Value("${verify.issuers_path}") Resource issuersResource,
+ @Value("${nudge_eduid_app_days}") int nudgeAppDays,
ServicesConfiguration servicesConfiguration) throws IOException {
this.userRepository = userRepository;
this.userCredentialRepository = userCredentialRepository;
@@ -146,6 +148,7 @@ public UserController(UserRepository userRepository,
this.relyingParty = relyingParty(rpId, rpOrigin);
this.emailGuessingPreventor = new EmailGuessingPrevention(emailGuessingSleepMillis);
this.featureDefaultRememberMe = featureDefaultRememberMe;
+ this.nudgeAppDays = nudgeAppDays;
List idinIssuers = objectMapper.readValue(issuersResource.getInputStream(), new TypeReference<>() {
});
@@ -369,6 +372,9 @@ public ResponseEntity createEduIDAccount(@Valid @RequestBody Cre
createAccount.getRelyingPartClientId(),
manage);
user.setCreateFromInstitutionKey(institution.getHash());
+ //Don't bother with the nudge app the next 24 hours
+ long nudgeAppMillis = System.currentTimeMillis() - (1000L * 60 * 60 * 24 * (nudgeAppDays - 1));
+ user.setLastSeenAppNudge(nudgeAppMillis);
user.validate();
userRepository.save(user);
diff --git a/myconext-server/src/main/java/myconext/model/User.java b/myconext-server/src/main/java/myconext/model/User.java
index c055c389..99b1f665 100644
--- a/myconext-server/src/main/java/myconext/model/User.java
+++ b/myconext-server/src/main/java/myconext/model/User.java
@@ -83,7 +83,7 @@ public class User implements Serializable, UserDetails {
private List eduIDS = new ArrayList<>();
private long created;
- private long updatedAt = System.currentTimeMillis() / 1000L;
+ private long updatedAt;
@Setter
@Indexed
private String trackingUuid;
@@ -116,7 +116,6 @@ public User(String uid, String email, String chosenName, String givenName, Strin
}
this.newUser = true;
this.created = System.currentTimeMillis() / 1000L;
- this.updatedAt = created;
}
public User(String uid, String email, String chosenName, String givenName, String familyName,
@@ -186,6 +185,7 @@ public String computeEduIdForIdentityProviderProviderIfAbsent(RemoteProvider rem
}
private String doComputeEduIDIfAbsent(ServiceProvider serviceProvider, Manage manage) {
+ this.updatedAt = System.currentTimeMillis();
serviceProvider.setLastLogin(new Date());
String institutionGuid = serviceProvider.getInstitutionGuid();
String entityId = serviceProvider.getEntityId();
diff --git a/myconext-server/src/main/java/myconext/security/GuestIdpAuthenticationRequestFilter.java b/myconext-server/src/main/java/myconext/security/GuestIdpAuthenticationRequestFilter.java
index 45b3c5c2..af7c035c 100644
--- a/myconext-server/src/main/java/myconext/security/GuestIdpAuthenticationRequestFilter.java
+++ b/myconext-server/src/main/java/myconext/security/GuestIdpAuthenticationRequestFilter.java
@@ -456,10 +456,11 @@ private boolean checkStepUp(HttpServletResponse response, HttpServletRequest req
!hasStudentAffiliation;
boolean missingValidName = !CollectionUtils.isEmpty(authenticationContextClassReferences) && authenticationContextClassReferences.contains(ACR.VALIDATE_NAMES) &&
!hasValidatedName(user);
-
if (user.isNewUser()) {
user.setNewUser(false);
- user.setLastSeenAppNudge(System.currentTimeMillis());
+ //ensure the user is the coming 24 hours is not nudged to the app
+ long nudgeAppMillis = System.currentTimeMillis() - (1000L * 60 * 60 * 24 * (nudgeAppDays - 1));
+ user.setLastSeenAppNudge(nudgeAppMillis);
userRepository.save(user);
logWithContext(user, "add", "account", LOG, "Saving user after new registration and magic link");
@@ -474,13 +475,8 @@ private boolean checkStepUp(HttpServletResponse response, HttpServletRequest req
if (samlAuthenticationRequest.isTiqrFlow()) {
return true;
}
- String url = this.redirectUrl + "/confirm?h=" + hash +
- "&redirect=" + URLEncoder.encode(this.magicLinkUrl, charSet) +
- "&email=" + URLEncoder.encode(user.getEmail(), charSet) +
- "&new=true";
- if (!StepUpStatus.NONE.equals(samlAuthenticationRequest.getSteppedUp())) {
- url += "&explanation=" + explanation;
- }
+ //we don't redirect the user to the nudge app page anymore
+ String url = String.format("%s?h=%s&force=true", this.magicLinkUrl, hash);
response.sendRedirect(url);
return false;
} else if (inStepUpFlow) {
@@ -499,7 +495,7 @@ private boolean checkStepUp(HttpServletResponse response, HttpServletRequest req
return false;
} else if (!samlAuthenticationRequest.isPasswordOrWebAuthnFlow() && !samlAuthenticationRequest.isTiqrFlow() &&
!user.loginOptions().contains(LoginOptions.APP.getValue()) &&
- user.getLastSeenAppNudge() < (System.currentTimeMillis() - 1000L * 60 * 60 * 24 * nudgeAppDays)) {
+ user.getLastSeenAppNudge() < (System.currentTimeMillis() - (1000L * 60 * 60 * 24 * nudgeAppDays))) {
//Nudge user to use the app
user.setLastSeenAppNudge(System.currentTimeMillis());
userRepository.save(user);
diff --git a/myconext-server/src/test/java/myconext/api/UserControllerTest.java b/myconext-server/src/test/java/myconext/api/UserControllerTest.java
index 28d29ea7..c0615886 100644
--- a/myconext-server/src/test/java/myconext/api/UserControllerTest.java
+++ b/myconext-server/src/test/java/myconext/api/UserControllerTest.java
@@ -98,11 +98,18 @@ public void newUserProvisioned() throws IOException {
User user = user("new@example.com", "Mary", "Doe", "en");
MagicLinkResponse magicLinkResponse = magicLinkRequest(user, HttpMethod.POST);
- assertEquals(user.getGivenName(), userRepository.findUserByEmail(user.getEmail()).get().getGivenName());
+ User userFromDB = userRepository.findUserByEmail(user.getEmail()).get();
+ assertEquals(0L, userFromDB.getLastSeenAppNudge());
+ assertEquals(user.getGivenName(), userFromDB.getGivenName());
String samlResponse = samlResponse(magicLinkResponse);
assertTrue(samlResponse.contains("new@example.com"));
+ User userFromAfter = userRepository.findUserByEmail(user.getEmail()).get();
+ long appNudgeDiff = System.currentTimeMillis() - userFromAfter.getLastSeenAppNudge();
+ int days = (int) Math.floor((double) appNudgeDiff / (1000 * 60 * 60 * 24));
+ assertEquals(6, days);
+
when()
.get("/myconext/api/idp/resend_magic_link_request?id=" + magicLinkResponse.authenticationRequestId)
.then()