Repository: govuk-one-login/authentication-api
Pull request #6427: ATO-1128: migrate away from using user profile
Author: login: GHSwallow
Created: 2025-04-29T13:40:40Z | Merged: 2025-04-30T13:17:18Z

### Wider context of change
Final migration in the email migration work. Migrates ProcessingIdentityHandler.

### What’s changed
- Swaps getting email from the session to the request. 
- Swaps getting internalCommonSubjectId from calculating via UserProfile to getting from the orchSession.
- Removes the now unused UserProfile from the handler

### Manual testing
TBD: Deploy to dev and test

[Logs to verify email is in sync](https://gds.splunkcloud.com/en-GB/app/search/search?q=search%20index%3D%22gds_di_production%22%20message%3D%22is%20email%20in%20sync*%22&display.page.search.mode=smart&dispatch.sample_ratio=1&workload_pool=&earliest=1745920800&latest=1746021600&display.page.search.tab=events&display.page.search.patterns.sensitivity=0.866&display.general.type=events&sid=1746018261.60231)
[Logs to verify internalCommonSubjectId is in sync](https://gds.splunkcloud.com/en-GB/app/search/search?q=search%20index%3D%22gds_di_production%22%20message%3D%22is%20internalCommonSubjectId%20in%20sync*%22&display.page.search.mode=smart&dispatch.sample_ratio=1&workload_pool=&earliest=1745920800&latest=1746021600&display.page.search.tab=events&display.page.search.patterns.sensitivity=0.866&display.general.type=events&sid=1746018227.60200)

### Checklist
- [x] Lambdas have correct permissions for the resources they're accessing. **No new resources accessed**
- [x] Impact on orch and auth mutual dependencies has been checked. **Yes**
- [x] Changes have been made to contract tests or not required. **N/A**
- [x] Changes have been made to the simulator or not required. **N/A**
- [x] Changes have been made to stubs or not required. **N/A**
- [x] Successfully deployed to authdev or not required. **N/A**
- [x] Successfully run Authentication acceptance tests against sandpit or not required. **N/A**



Diff:
diff --git a/integration-tests/src/test/java/uk/gov/di/authentication/api/ProcessingIdentityIntegrationTest.java b/integration-tests/src/test/java/uk/gov/di/authentication/api/ProcessingIdentityIntegrationTest.java
index ec6afc2b911..e60596e20de 100644
--- a/integration-tests/src/test/java/uk/gov/di/authentication/api/ProcessingIdentityIntegrationTest.java
+++ b/integration-tests/src/test/java/uk/gov/di/authentication/api/ProcessingIdentityIntegrationTest.java
@@ -21,6 +21,7 @@
 import uk.gov.di.orchestration.shared.entity.OrchSessionItem;
 import uk.gov.di.orchestration.shared.entity.ServiceType;
 import uk.gov.di.orchestration.shared.entity.VectorOfTrust;
+import uk.gov.di.orchestration.shared.helpers.SaltHelper;
 import uk.gov.di.orchestration.shared.serialization.Json;
 import uk.gov.di.orchestration.sharedtest.basetest.ApiGatewayHandlerIntegrationTest;
 import uk.gov.di.orchestration.sharedtest.extensions.OrchClientSessionExtension;
@@ -60,6 +61,7 @@ public class ProcessingIdentityIntegrationTest extends ApiGatewayHandlerIntegrat
     public static final State STATE = new State();
     public static final String ENCODED_DEVICE_INFORMATION =
             "R21vLmd3QilNKHJsaGkvTFxhZDZrKF44SStoLFsieG0oSUY3aEhWRVtOMFRNMVw1dyInKzB8OVV5N09hOi8kLmlLcWJjJGQiK1NPUEJPPHBrYWJHP358NDg2ZDVc";
+    private static final byte[] SALT = SaltHelper.generateNewSalt();
 
     @RegisterExtension
     protected static final OrchSessionExtension orchSessionExtension = new OrchSessionExtension();
@@ -81,10 +83,9 @@ void shouldReturnStatusOfCOMPLETEDWhenEntryInDatabaseAndJWTIsPresent()
             throws Json.JsonException {
         setupSession(false);
         setupClient();
-        byte[] salt = setupUser();
         var signedCredential = SignedCredentialHelper.generateCredential();
         var pairwiseIdentifier =
-                calculatePairwiseIdentifier(INTERNAL_SUBJECT.getValue(), "test.com", salt);
+                calculatePairwiseIdentifier(INTERNAL_SUBJECT.getValue(), "test.com", SALT);
         identityStore.addCoreIdentityJWT(
                 CLIENT_SESSION_ID, pairwiseIdentifier, signedCredential.serialize());
 
@@ -113,9 +114,8 @@ void shouldReturnStatusOfPROCESSINGWhenEntryInDatabaseButNoJWTIsPresent()
             throws Json.JsonException {
         setupSession(false);
         setupClient();
-        byte[] salt = setupUser();
         var pairwiseIdentifier =
-                calculatePairwiseIdentifier(INTERNAL_SUBJECT.getValue(), "test.com", salt);
+                calculatePairwiseIdentifier(INTERNAL_SUBJECT.getValue(), "test.com", SALT);
         identityStore.saveIdentityClaims(
                 CLIENT_SESSION_ID,
                 pairwiseIdentifier,
@@ -148,7 +148,6 @@ void shouldReturnStatusOfERRORWhenEntryIsNotInDatabaseOnSecondAttempt()
             throws Json.JsonException {
         setupSession(true);
         setupClient();
-        setupUser();
 
         Map<String, String> headers = new HashMap<>();
         headers.put("Session-Id", SESSION_ID);
@@ -175,7 +174,6 @@ void shouldReturnStatusOfNO_ENTRYWhenEntryIsNotInDatabaseOnFirstAttempt()
             throws Json.JsonException {
         setupSession(false);
         setupClient();
-        setupUser();
 
         Map<String, String> headers = new HashMap<>();
         headers.put("Session-Id", SESSION_ID);
@@ -251,9 +249,4 @@ private void setupClient() {
                 ES256.getName(),
                 true);
     }
-
-    private byte[] setupUser() {
-        userStore.signUp(TEST_EMAIL_ADDRESS, "password-1", INTERNAL_SUBJECT);
-        return userStore.addSalt(TEST_EMAIL_ADDRESS);
-    }
 }
diff --git a/ipv-api/src/main/java/uk/gov/di/authentication/ipv/lambda/ProcessingIdentityHandler.java b/ipv-api/src/main/java/uk/gov/di/authentication/ipv/lambda/ProcessingIdentityHandler.java
index 1829ecfd24d..d8692c496c4 100644
--- a/ipv-api/src/main/java/uk/gov/di/authentication/ipv/lambda/ProcessingIdentityHandler.java
+++ b/ipv-api/src/main/java/uk/gov/di/authentication/ipv/lambda/ProcessingIdentityHandler.java
@@ -15,8 +15,6 @@
 import uk.gov.di.orchestration.shared.entity.ClientRegistry;
 import uk.gov.di.orchestration.shared.entity.DestroySessionsRequest;
 import uk.gov.di.orchestration.shared.entity.ResponseHeaders;
-import uk.gov.di.orchestration.shared.entity.UserProfile;
-import uk.gov.di.orchestration.shared.helpers.ClientSubjectHelper;
 import uk.gov.di.orchestration.shared.helpers.IpAddressHelper;
 import uk.gov.di.orchestration.shared.helpers.PersistentIdHelper;
 import uk.gov.di.orchestration.shared.lambda.BaseFrontendHandler;
@@ -35,10 +33,10 @@
 import uk.gov.di.orchestration.shared.services.SessionService;
 import uk.gov.di.orchestration.shared.state.UserContext;
 
-import java.net.URI;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Objects;
+import java.util.Optional;
 
 import static uk.gov.di.orchestration.shared.helpers.ApiGatewayResponseHelper.generateApiGatewayProxyResponse;
 import static uk.gov.di.orchestration.shared.helpers.AuditHelper.attachTxmaAuditFieldFromHeaders;
@@ -123,35 +121,7 @@ public APIGatewayProxyResponseEvent handleRequestWithUserContext(
         LOG.info("ProcessingIdentity request received");
         attachTxmaAuditFieldFromHeaders(input.getHeaders());
         try {
-            UserProfile userProfile = userContext.getUserProfile().orElseThrow();
             ClientRegistry client = userContext.getClient().orElseThrow();
-            var rpPairwiseSubject =
-                    ClientSubjectHelper.getSubject(
-                            userProfile,
-                            client,
-                            authenticationService,
-                            configurationService.getInternalSectorURI());
-            var internalPairwiseSubjectId =
-                    ClientSubjectHelper.calculatePairwiseIdentifier(
-                            userProfile.getSubjectID(),
-                            URI.create(configurationService.getInternalSectorURI()),
-                            authenticationService.getOrGenerateSalt(userProfile));
-
-            // TODO: ATO-1128: temp logs to verify values are in sync:
-            try {
-                LOG.info(
-                        "is internalCommonSubjectId in sync {}",
-                        Objects.equals(
-                                userContext.getOrchSession().getInternalCommonSubjectId(),
-                                internalPairwiseSubjectId));
-
-                LOG.info(
-                        "is email in sync {}",
-                        Objects.equals(request.getEmail(), userProfile.getEmail()));
-            } catch (Exception e) {
-                LOG.info("temp logs failed, message: {}", e.getMessage());
-            }
-            //
 
             int processingAttempts =
                     userContext.getOrchSession().incrementProcessingIdentityAttempts();
@@ -185,10 +155,7 @@ public APIGatewayProxyResponseEvent handleRequestWithUserContext(
                             userContext.getSessionId(),
                             client.getClientID(),
                             AuditService.UNKNOWN,
-                            userContext
-                                    .getUserProfile()
-                                    .map(UserProfile::getEmail)
-                                    .orElse(AuditService.UNKNOWN),
+                            Optional.ofNullable(request.getEmail()).orElse(AuditService.UNKNOWN),
                             IpAddressHelper.extractIpAddress(input),
                             AuditService.UNKNOWN,
                             PersistentIdHelper.extractPersistentIdFromHeaders(input.getHeaders()));
@@ -205,7 +172,10 @@ public APIGatewayProxyResponseEvent handleRequestWithUserContext(
                                 "AIS: getAccountIntervention",
                                 () ->
                                         accountInterventionService.getAccountIntervention(
-                                                internalPairwiseSubjectId, auditContext));
+                                                userContext
+                                                        .getOrchSession()
+                                                        .getInternalCommonSubjectId(),
+                                                auditContext));
                 if (configurationService.isAccountInterventionServiceActionEnabled()
                         && (intervention.getSuspended() || intervention.getBlocked())) {
                     return performIntervention(input, userContext, client, intervention);
@@ -219,9 +189,8 @@ public APIGatewayProxyResponseEvent handleRequestWithUserContext(
             LOG.error("Unable to generate ProcessingIdentityResponse");
             throw new RuntimeException();
         } catch (NoSuchElementException e) {
-            LOG.warn(
-                    "Issue retrieving UserProfile or ClientRegistry from UserContext. UserProfile is present: {}, ClientRegistry is present: {}",
-                    userContext.getUserProfile().isPresent(),
+            LOG.error(
+                    "Issue retrieving ClientRegistry from UserContext. ClientRegistry is present: {}",
                     userContext.getClient().isPresent());
             throw new RuntimeException();
         }
diff --git a/ipv-api/src/test/java/uk/gov/di/authentication/ipv/lambda/ProcessingIdentityHandlerTest.java b/ipv-api/src/test/java/uk/gov/di/authentication/ipv/lambda/ProcessingIdentityHandlerTest.java
index d5177fb74ed..87d3fd13075 100644
--- a/ipv-api/src/test/java/uk/gov/di/authentication/ipv/lambda/ProcessingIdentityHandlerTest.java
+++ b/ipv-api/src/test/java/uk/gov/di/authentication/ipv/lambda/ProcessingIdentityHandlerTest.java
@@ -10,6 +10,7 @@
 import com.nimbusds.openid.connect.sdk.OIDCScopeValue;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 import software.amazon.awssdk.core.SdkBytes;
 import uk.gov.di.authentication.ipv.entity.ProcessingIdentityInterventionResponse;
 import uk.gov.di.authentication.ipv.entity.ProcessingIdentityResponse;
@@ -24,9 +25,8 @@
 import uk.gov.di.orchestration.shared.entity.OrchSessionItem;
 import uk.gov.di.orchestration.shared.entity.ResponseHeaders;
 import uk.gov.di.orchestration.shared.entity.Session;
-import uk.gov.di.orchestration.shared.entity.UserProfile;
 import uk.gov.di.orchestration.shared.helpers.ClientSubjectHelper;
-import uk.gov.di.orchestration.shared.helpers.NowHelper;
+import uk.gov.di.orchestration.shared.lambda.BaseFrontendHandler;
 import uk.gov.di.orchestration.shared.serialization.Json;
 import uk.gov.di.orchestration.shared.services.AccountInterventionService;
 import uk.gov.di.orchestration.shared.services.AuditService;
@@ -40,13 +40,12 @@
 import uk.gov.di.orchestration.shared.services.OrchSessionService;
 import uk.gov.di.orchestration.shared.services.SerializationService;
 import uk.gov.di.orchestration.shared.services.SessionService;
+import uk.gov.di.orchestration.sharedtest.logging.CaptureLoggingExtension;
 
 import java.net.URI;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
-import java.time.temporal.ChronoUnit;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -56,6 +55,7 @@
 import static java.util.Collections.singletonList;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasItem;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
@@ -67,6 +67,7 @@
 import static uk.gov.di.orchestration.shared.domain.RequestHeaders.SESSION_ID_HEADER;
 import static uk.gov.di.orchestration.shared.helpers.ApiGatewayResponseHelper.generateApiGatewayProxyResponse;
 import static uk.gov.di.orchestration.sharedtest.helper.RequestEventHelper.contextWithSourceIp;
+import static uk.gov.di.orchestration.sharedtest.logging.LogEventMatcher.withMessageContaining;
 import static uk.gov.di.orchestration.sharedtest.matchers.APIGatewayProxyResponseEventMatcher.hasBody;
 import static uk.gov.di.orchestration.sharedtest.matchers.APIGatewayProxyResponseEventMatcher.hasStatus;
 
@@ -77,10 +78,6 @@ class ProcessingIdentityHandlerTest {
     private static final String EMAIL_ADDRESS = "test@test.com";
     private static final String CLIENT_ID = "test-client-id";
     private static final String CLIENT_NAME = "test-client-name";
-    private static final String PHONE_NUMBER = "01234567890";
-    private static final Date CREATED_DATE_TIME = NowHelper.nowMinus(30, ChronoUnit.SECONDS);
-    private static final Date UPDATED_DATE_TIME = NowHelper.now();
-    private static final String PUBLIC_SUBJECT_ID = new Subject("public-subject-id-2").getValue();
     private static final String SUBJECT_ID = new Subject("subject-id-3").getValue();
     private static final ByteBuffer SALT =
             ByteBuffer.wrap("a-test-salt".getBytes(StandardCharsets.UTF_8));
@@ -110,19 +107,20 @@ class ProcessingIdentityHandlerTest {
     private final OrchClientSessionService orchClientSessionService =
             mock(OrchClientSessionService.class);
     private final Session session = new Session();
-    private final OrchSessionItem orchSession = new OrchSessionItem(SESSION_ID);
+    private final OrchSessionItem orchSession =
+            new OrchSessionItem(SESSION_ID).withInternalCommonSubjectId(PAIRWISE_SUBJECT);
     private final APIGatewayProxyRequestEvent event = new APIGatewayProxyRequestEvent();
     protected final Json objectMapper = SerializationService.getInstance();
     private ProcessingIdentityHandler handler;
 
+    @RegisterExtension
+    private final CaptureLoggingExtension logging =
+            new CaptureLoggingExtension(BaseFrontendHandler.class);
+
     @BeforeEach
     void setup() {
-        var userProfile = generateUserProfile();
         when(dynamoClientService.getClient(CLIENT_ID))
                 .thenReturn(Optional.of(generateClientRegistry()));
-        when(dynamoService.getUserProfileFromEmail(EMAIL_ADDRESS))
-                .thenReturn(Optional.of(userProfile));
-        when(dynamoService.getOrGenerateSalt(userProfile)).thenReturn(SALT.array());
         when(configurationService.getEnvironment()).thenReturn(ENVIRONMENT);
         when(configurationService.getInternalSectorURI()).thenReturn(INTERNAL_SECTOR_URI);
         Map<String, String> headers = new HashMap<>();
@@ -167,6 +165,22 @@ void shouldReturnErrorIfOrchSessionIsNotFound() throws Json.JsonException {
         verifyNoInteractions(cloudwatchMetricsService);
     }
 
+    @Test
+    void shouldReturnErrorIfOrchSessionHasNoInternalCommonSubjectId() throws Json.JsonException {
+        when(sessionService.getSession(anyString())).thenReturn(Optional.of(session));
+        when(orchSessionService.getSession(anyString()))
+                .thenReturn(Optional.of(new OrchSessionItem(SESSION_ID)));
+
+        var result = handler.handleRequest(event, context);
+
+        assertThat(result, hasStatus(400));
+        assertThat(result, hasBody(objectMapper.writeValueAsString(ErrorResponse.ERROR_1000)));
+        verifyNoInteractions(cloudwatchMetricsService);
+        assertThat(
+                logging.events(),
+                hasItem(withMessageContaining("Orch session has no internalCommonSubjectId")));
+    }
+
     @Test
     void shouldReturnCOMPLETEDStatusWhenIdentityCredentialIsPresent() throws Json.JsonException {
         usingValidSession();
@@ -259,7 +273,7 @@ void shouldInterveneIfAccountInterventionServiceActionIsEnabledAndProcessingStat
         verify(logoutService)
                 .handleAccountInterventionLogout(
                         new DestroySessionsRequest(SESSION_ID, List.of()),
-                        null,
+                        PAIRWISE_SUBJECT,
                         event,
                         CLIENT_ID,
                         intervention);
@@ -399,17 +413,4 @@ private ClientRegistry generateClientRegistry() {
                 .withCookieConsentShared(true)
                 .withSubjectType("pairwise");
     }
-
-    private UserProfile generateUserProfile() {
-        return new UserProfile()
-                .withEmail(EMAIL_ADDRESS)
-                .withEmailVerified(true)
-                .withPhoneNumber(PHONE_NUMBER)
-                .withPhoneNumberVerified(true)
-                .withPublicSubjectID(PUBLIC_SUBJECT_ID)
-                .withSubjectID(SUBJECT_ID)
-                .withSalt(SALT)
-                .withCreated(CREATED_DATE_TIME.toString())
-                .withUpdated(UPDATED_DATE_TIME.toString());
-    }
 }
diff --git a/orchestration-shared/src/main/java/uk/gov/di/orchestration/shared/lambda/BaseFrontendHandler.java b/orchestration-shared/src/main/java/uk/gov/di/orchestration/shared/lambda/BaseFrontendHandler.java
index dd76a3c33d0..a5e0e87dfba 100644
--- a/orchestration-shared/src/main/java/uk/gov/di/orchestration/shared/lambda/BaseFrontendHandler.java
+++ b/orchestration-shared/src/main/java/uk/gov/di/orchestration/shared/lambda/BaseFrontendHandler.java
@@ -7,7 +7,6 @@
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.ThreadContext;
-import uk.gov.di.orchestration.shared.entity.BaseFrontendRequest;
 import uk.gov.di.orchestration.shared.entity.ErrorResponse;
 import uk.gov.di.orchestration.shared.entity.OrchClientSessionItem;
 import uk.gov.di.orchestration.shared.entity.OrchSessionItem;
@@ -28,7 +27,6 @@
 import uk.gov.di.orchestration.shared.services.SessionService;
 import uk.gov.di.orchestration.shared.state.UserContext;
 
-import java.util.Locale;
 import java.util.Optional;
 
 import static uk.gov.di.orchestration.shared.domain.RequestHeaders.CLIENT_SESSION_ID_HEADER;
@@ -156,6 +154,12 @@ private APIGatewayProxyResponseEvent validateAndHandleRequest(
                 PERSISTENT_SESSION_ID,
                 PersistentIdHelper.extractPersistentIdFromHeaders(input.getHeaders()));
 
+        if (orchSession.get().getInternalCommonSubjectId() == null
+                || orchSession.get().getInternalCommonSubjectId().isBlank()) {
+            LOG.warn("Orch session has no internalCommonSubjectId");
+            return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1000);
+        }
+
         Optional<String> userLanguage =
                 getUserLanguageFromRequestHeaders(input.getHeaders(), configurationService);
         final T request;
@@ -184,24 +188,6 @@ private APIGatewayProxyResponseEvent validateAndHandleRequest(
 
         orchClientSession.ifPresent(userContextBuilder::withOrchClientSession);
 
-        session.map(Session::getEmailAddress)
-                .map(authenticationService::getUserProfileFromEmail)
-                .ifPresentOrElse(
-                        userProfile ->
-                                userContextBuilder
-                                        .withUserProfile(userProfile)
-                                        .withUserAuthenticated(true),
-                        () -> {
-                            if (request instanceof BaseFrontendRequest baseFrontendRequest)
-                                userContextBuilder
-                                        .withUserProfile(
-                                                authenticationService.getUserProfileFromEmail(
-                                                        baseFrontendRequest
-                                                                .getEmail()
-                                                                .toLowerCase(Locale.ROOT)))
-                                        .withUserAuthenticated(false);
-                        });
-
         userContextBuilder.withUserLanguage(matchSupportedLanguage(userLanguage));
 
         return handleRequestWithUserContext(input, context, request, userContextBuilder.build());
diff --git a/orchestration-shared/src/main/java/uk/gov/di/orchestration/shared/state/UserContext.java b/orchestration-shared/src/main/java/uk/gov/di/orchestration/shared/state/UserContext.java
index 160315b2dec..7360c15a7b8 100644
--- a/orchestration-shared/src/main/java/uk/gov/di/orchestration/shared/state/UserContext.java
+++ b/orchestration-shared/src/main/java/uk/gov/di/orchestration/shared/state/UserContext.java
@@ -5,7 +5,6 @@
 import uk.gov.di.orchestration.shared.entity.OrchSessionItem;
 import uk.gov.di.orchestration.shared.entity.Session;
 import uk.gov.di.orchestration.shared.entity.UserCredentials;
-import uk.gov.di.orchestration.shared.entity.UserProfile;
 import uk.gov.di.orchestration.shared.helpers.LocaleHelper.SupportedLanguage;
 
 import java.util.Optional;
@@ -13,9 +12,7 @@
 public class UserContext {
     private final Session session;
     private final String sessionId;
-    private final Optional<UserProfile> userProfile;
     private final Optional<UserCredentials> userCredentials;
-    private final boolean userAuthenticated;
     private final Optional<ClientRegistry> client;
     private final OrchClientSessionItem orchClientSession;
     private final SupportedLanguage userLanguage;
@@ -25,9 +22,7 @@ public class UserContext {
     protected UserContext(
             Session session,
             String sessionId,
-            Optional<UserProfile> userProfile,
             Optional<UserCredentials> userCredentials,
-            boolean userAuthenticated,
             Optional<ClientRegistry> client,
             OrchClientSessionItem orchClientSession,
             SupportedLanguage userLanguage,
@@ -35,9 +30,7 @@ protected UserContext(
             OrchSessionItem orchSession) {
         this.session = session;
         this.sessionId = sessionId;
-        this.userProfile = userProfile;
         this.userCredentials = userCredentials;
-        this.userAuthenticated = userAuthenticated;
         this.client = client;
         this.orchClientSession = orchClientSession;
         this.userLanguage = userLanguage;
@@ -53,18 +46,10 @@ public String getSessionId() {
         return sessionId;
     }
 
-    public Optional<UserProfile> getUserProfile() {
-        return userProfile;
-    }
-
     public Optional<UserCredentials> getUserCredentials() {
         return userCredentials;
     }
 
-    public boolean isUserAuthenticated() {
-        return userAuthenticated;
-    }
-
     public Optional<ClientRegistry> getClient() {
         return client;
     }
@@ -100,9 +85,7 @@ public static Builder builder(Session session) {
     public static class Builder {
         private final Session session;
         private String sessionId;
-        private Optional<UserProfile> userProfile = Optional.empty();
         private Optional<UserCredentials> userCredentials = Optional.empty();
-        private boolean userAuthenticated = false;
         private Optional<ClientRegistry> client = Optional.empty();
         private OrchClientSessionItem orchClientSession;
         private SupportedLanguage userLanguage;
@@ -118,25 +101,11 @@ public Builder withSessionId(String sessionId) {
             return this;
         }
 
-        public Builder withUserProfile(UserProfile userProfile) {
-            return withUserProfile(Optional.of(userProfile));
-        }
-
-        public Builder withUserProfile(Optional<UserProfile> userProfile) {
-            this.userProfile = userProfile;
-            return this;
-        }
-
         public Builder withUserCredentials(Optional<UserCredentials> userCredentials) {
             this.userCredentials = userCredentials;
             return this;
         }
 
-        public Builder withUserAuthenticated(boolean userAuthenticated) {
-            this.userAuthenticated = userAuthenticated;
-            return this;
-        }
-
         public Builder withClient(ClientRegistry client) {
             return withClient(Optional.of(client));
         }
@@ -170,9 +139,7 @@ public UserContext build() {
             return new UserContext(
                     session,
                     sessionId,
-                    userProfile,
                     userCredentials,
-                    userAuthenticated,
                     client,
                     orchClientSession,
                     userLanguage,


Reviews:
user: login: Ryan-Andrews99
body: One small comment about a log level, isn't blocking, but rest looks good! Approving subject to testing in dev 🚀 
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T15:47:26Z
user: login: GHSwallow
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T15:58:21Z
user: login: Ryan-Andrews99
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T16:01:22Z

Review comments:
diff_hunk: @@ -192,8 +190,7 @@ public APIGatewayProxyResponseEvent handleRequestWithUserContext(
             throw new RuntimeException();
         } catch (NoSuchElementException e) {
             LOG.warn(
-                    "Issue retrieving UserProfile or ClientRegistry from UserContext. UserProfile is present: {}, ClientRegistry is present: {}",
-                    userContext.getUserProfile().isPresent(),
+                    "Issue retrieving ClientRegistry from UserContext. ClientRegistry is present: {}",
                     userContext.getClient().isPresent());
path: ipv-api/src/main/java/uk/gov/di/authentication/ipv/lambda/ProcessingIdentityHandler.java
user: login: Ryan-Andrews99
body: I would vote to make this an error log. The likelihood of this ever being hit is tiny, but given it now only represents a missing client (and not also a user profile) I think it makes sense to bump this to an error. What do you think?
created_at: 2025-04-29T15:43:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -15,7 +15,6 @@ public class UserContext {
     private final String sessionId;
     private final Optional<UserProfile> userProfile;
     private final Optional<UserCredentials> userCredentials;
-    private final boolean userAuthenticated;
path: orchestration-shared/src/main/java/uk/gov/di/orchestration/shared/state/UserContext.java
user: login: Ryan-Andrews99
body: Nice!
created_at: 2025-04-29T15:44:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -192,8 +190,7 @@ public APIGatewayProxyResponseEvent handleRequestWithUserContext(
             throw new RuntimeException();
         } catch (NoSuchElementException e) {
             LOG.warn(
-                    "Issue retrieving UserProfile or ClientRegistry from UserContext. UserProfile is present: {}, ClientRegistry is present: {}",
-                    userContext.getUserProfile().isPresent(),
+                    "Issue retrieving ClientRegistry from UserContext. ClientRegistry is present: {}",
                     userContext.getClient().isPresent());
path: ipv-api/src/main/java/uk/gov/di/authentication/ipv/lambda/ProcessingIdentityHandler.java
user: login: GHSwallow
body: ooh that's a good point, yea I agree
created_at: 2025-04-29T15:58:21Z
author_association: CONTRIBUTOR

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-04-29T16:13:32Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=govuk-one-login_authentication-api&pullRequest=6427) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=govuk-one-login_authentication-api&pullRequest=6427&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=govuk-one-login_authentication-api&pullRequest=6427&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=govuk-one-login_authentication-api&pullRequest=6427&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [83.3% Coverage on New Code](https://sonarcloud.io/component_measures?id=govuk-one-login_authentication-api&pullRequest=6427&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=govuk-one-login_authentication-api&pullRequest=6427&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=govuk-one-login_authentication-api&pullRequest=6427)


author_association: NONE