fix: Update security context via reactive context repository instead of directly updating session attributes (#40892)

## Description
This PR fixes the security context persistence mechanism in the email
verification flow. Previously, the code was directly manipulating the
session attributes to store the security context, which is not the
recommended approach in Spring WebFlux applications. We've updated the
implementation to use the proper ServerSecurityContextRepository for
persisting the security context.

### Changes
Existing implementation:
```
session.getAttributes().put(DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME, securityContext);
```
Drawbacks:
- Bypassed Spring Security's security context management
- Didn't properly integrate with reactive patterns
- Could lead to session consistency issues
- Wasn't compatible with different security context storage strategies

Updated implementation:
```
ServerSecurityContextRepository contextRepository = new WebSessionServerSecurityContextRepository();
return contextRepository.save(exchange, securityContext)
    .then(repository.save(user));
```

Advantages: 
- Proper integration with Spring Security's reactive architecture
- Thread-safe security context persistence
- Better session management
- Future compatibility with different session storage mechanisms

Ref thread:
https://theappsmith.slack.com/archives/C02K2MZERSL/p1749434009167839

/test Authentication,Email

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/15532462184>
> Commit: 42445874aafe300c6791cb45388eb0d778e56fba
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=15532462184&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.Authentication, @tag.Email`
> Spec:
> <hr>Mon, 09 Jun 2025 10:49:28 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Bug Fixes**
- Improved email verification process for a more reliable and consistent
user authentication experience.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Abhijeet 2025-06-09 16:20:45 +05:30 committed by GitHub
parent 99db0a1fae
commit 2d890df892
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -53,6 +53,8 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.DefaultServerRedirectStrategy;
import org.springframework.security.web.server.ServerRedirectStrategy;
import org.springframework.security.web.server.WebFilterExchange;
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
@ -85,7 +87,6 @@ import static com.appsmith.server.helpers.ValidationUtils.LOGIN_PASSWORD_MIN_LEN
import static com.appsmith.server.helpers.ValidationUtils.validateUserPassword;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import static org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository.DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME;
@Slf4j
public class UserServiceCEImpl extends BaseService<UserRepository, User, String> implements UserServiceCE {
@ -999,16 +1000,17 @@ public class UserServiceCEImpl extends BaseService<UserRepository, User, String>
webFilterExchange.getExchange(), URI.create(errorRedirectUrl1));
}
user.setEmailVerified(TRUE);
Authentication authentication =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
securityContext.setAuthentication(authentication);
session.getAttributes().put(DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME, securityContext);
user.setEmailVerified(TRUE);
Mono<Void> redirectionMono = redirectStrategy.sendRedirect(
webFilterExchange.getExchange(), URI.create(postVerificationRedirectUrl));
return repository.save(user).then(redirectionMono);
});
// Save the security context in the session
ServerSecurityContextRepository contextRepository =
new WebSessionServerSecurityContextRepository();
return contextRepository.save(exchange, securityContext).then(repository.save(user));
})
.then(redirectStrategy.sendRedirect(
webFilterExchange.getExchange(), URI.create(postVerificationRedirectUrl)));
});
}
}