diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java b/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java
index 202ca6dc..2f0ed7dd 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gbl/api/API.java
@@ -56,6 +56,7 @@ public final class API {
 
     public static final String OAUTH_ENDPOINT = "/oauth";
     public static final String OAUTH_TOKEN_ENDPOINT = OAUTH_ENDPOINT + "/token";
+    public static final String OAUTH_JWTTOKEN_ENDPOINT = OAUTH_ENDPOINT + "/jwttoken";
     public static final String OAUTH_REVOKE_TOKEN_ENDPOINT = OAUTH_ENDPOINT + "/revoke-token";
 
     public static final String CURRENT_USER_PATH_SEGMENT = "/me";
diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/ScreenProctoringSettings.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/ScreenProctoringSettings.java
index c99a1209..9d5a3ef5 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/ScreenProctoringSettings.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/exam/ScreenProctoringSettings.java
@@ -34,6 +34,8 @@ public class ScreenProctoringSettings {
     public static final String ATTR_SPS_ACCOUNT_ID = "spsAccountId";
     public static final String ATTR_SPS_ACCOUNT_PASSWORD = "spsAccountPassword";
 
+    public static final String ATTR_SPS_BUNDLED = "bundled";
+
     @JsonProperty(Domain.EXAM.ATTR_ID)
     public final Long examId;
 
@@ -62,6 +64,9 @@ public class ScreenProctoringSettings {
     @JsonProperty(ATTR_COLLECTING_GROUP_SIZE)
     public final Integer collectingGroupSize;
 
+    @JsonProperty(ATTR_SPS_BUNDLED)
+    public final boolean bundled;
+
     @JsonCreator
     public ScreenProctoringSettings(
             @JsonProperty(Domain.EXAM.ATTR_ID) final Long examId,
@@ -72,7 +77,8 @@ public class ScreenProctoringSettings {
             @JsonProperty(ATTR_SPS_ACCOUNT_ID) final String spsAccountId,
             @JsonProperty(ATTR_SPS_ACCOUNT_PASSWORD) final CharSequence spsAccountPassword,
             @JsonProperty(ATTR_COLLECTING_STRATEGY) final CollectingStrategy collectingStrategy,
-            @JsonProperty(ATTR_COLLECTING_GROUP_SIZE) final Integer collectingGroupSize) {
+            @JsonProperty(ATTR_COLLECTING_GROUP_SIZE) final Integer collectingGroupSize,
+            @JsonProperty(ATTR_SPS_BUNDLED) final boolean bundled) {
 
         this.examId = examId;
         this.enableScreenProctoring = enableScreenProctoring;
@@ -83,6 +89,30 @@ public class ScreenProctoringSettings {
         this.spsAccountPassword = spsAccountPassword;
         this.collectingStrategy = collectingStrategy;
         this.collectingGroupSize = collectingGroupSize;
+        this.bundled = bundled;
+    }
+
+    public ScreenProctoringSettings(
+            final Long examId,
+            final Boolean enableScreenProctoring,
+            final String spsServiceURL,
+            final String spsAPIKey,
+            final CharSequence spsAPISecret,
+            final String spsAccountId,
+            final CharSequence spsAccountPassword,
+            final CollectingStrategy collectingStrategy,
+            final Integer collectingGroupSize) {
+
+        this.examId = examId;
+        this.enableScreenProctoring = enableScreenProctoring;
+        this.spsServiceURL = spsServiceURL;
+        this.spsAPIKey = spsAPIKey;
+        this.spsAPISecret = spsAPISecret;
+        this.spsAccountId = spsAccountId;
+        this.spsAccountPassword = spsAccountPassword;
+        this.collectingStrategy = collectingStrategy;
+        this.collectingGroupSize = collectingGroupSize;
+        this.bundled = false;
     }
 
     public ScreenProctoringSettings(final Exam exam) {
@@ -108,6 +138,7 @@ public class ScreenProctoringSettings {
         this.collectingGroupSize = Integer.parseInt(exam.additionalAttributes.getOrDefault(
                 ATTR_COLLECTING_GROUP_SIZE,
                 "-1"));
+        this.bundled = false;
     }
 
     public Long getExamId() {
@@ -151,6 +182,10 @@ public class ScreenProctoringSettings {
         return Objects.hash(this.examId);
     }
 
+    public boolean isBundled() {
+        return this.bundled;
+    }
+
     @Override
     public boolean equals(final Object obj) {
         if (this == obj)
diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java
index 7e0d736b..af87fc40 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java
@@ -39,6 +39,7 @@ import java.util.stream.Collectors;
 
 import javax.validation.constraints.NotNull;
 
+import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.codec.binary.Hex;
 import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -919,4 +920,12 @@ public final class Utils {
                 .replaceAll("[^A-Za-z0-9_]", "");
     }
 
+    public static String createBasicAuthHeader(final String clientname, final CharSequence clientsecret) {
+        final String plainCreds = clientname + Constants.COLON + clientsecret;
+        final byte[] plainCredsBytes = plainCreds.getBytes();
+        final byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
+        final String base64Creds = new String(base64CredsBytes);
+        return "Basic " + base64Creds;
+    }
+
 }
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/ProctoringServlet.java b/src/main/java/ch/ethz/seb/sebserver/gui/ProctoringServlet.java
index 209eca4c..73321a3e 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/ProctoringServlet.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/ProctoringServlet.java
@@ -18,7 +18,6 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
-import org.apache.commons.lang3.BooleanUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpStatus;
@@ -26,21 +25,17 @@ import org.springframework.stereotype.Component;
 import org.springframework.web.context.WebApplicationContext;
 import org.springframework.web.context.support.WebApplicationContextUtils;
 
-import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
 import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
 import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.SEBServerAuthorizationContext;
 import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService;
 import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService.ProctoringWindowData;
-import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringGUIService.ScreenProctoringWindowData;
 import ch.ethz.seb.sebserver.gui.service.session.proctoring.ProctoringWindowScriptResolver;
 
 @Component
 @GuiProfile
 public class ProctoringServlet extends HttpServlet {
 
-    public static final String SCREEN_PROCOTRING_FLAG_PARAM = "screenproctoring";
-
     private static final long serialVersionUID = 3475978419653411800L;
     private static final Logger log = LoggerFactory.getLogger(ProctoringServlet.class);
 
@@ -63,54 +58,12 @@ public class ProctoringServlet extends HttpServlet {
         final WebApplicationContext webApplicationContext = WebApplicationContextUtils
                 .getRequiredWebApplicationContext(servletContext);
 
-        UserInfo user;
-        try {
-            user = isAuthenticated(httpSession, webApplicationContext);
-        } catch (final Exception e) {
+        final boolean authenticated = isAuthenticated(httpSession, webApplicationContext);
+        if (!authenticated) {
             resp.setStatus(HttpStatus.FORBIDDEN.value());
             return;
         }
 
-        final String parameter = req.getParameter(SCREEN_PROCOTRING_FLAG_PARAM);
-        if (BooleanUtils.toBoolean(parameter)) {
-            openScreenProctoring(req, resp, user, httpSession);
-        } else {
-            openRemoteProctoring(resp, httpSession);
-        }
-    }
-
-    private void openScreenProctoring(
-            final HttpServletRequest req,
-            final HttpServletResponse resp,
-            final UserInfo user,
-            final HttpSession httpSession) throws IOException {
-
-        final ScreenProctoringWindowData data = (ScreenProctoringWindowData) httpSession
-                .getAttribute(ProctoringGUIService.SESSION_ATTR_SCREEN_PROCTORING_DATA);
-
-        // NOTE: POST on data.loginLocation seems not to work for automated login
-        // TODO discuss with Nadim how to make a direct login POST on the GUI client
-        //      maybe there is a way to expose /login endpoint for directly POST credentials for login.
-
-        // https://stackoverflow.com/questions/46582/response-redirect-with-post-instead-of-get
-        final StringBuilder sb = new StringBuilder();
-//        sb.append("");
-//        sb.append("
");
-//        sb.append("");
-//        sb.append("");
-//        sb.append("");
-
-        resp.getOutputStream().println(sb.toString());
-    }
-
-    private void openRemoteProctoring(
-            final HttpServletResponse resp,
-            final HttpSession httpSession) throws IOException {
-
         final ProctoringWindowData proctoringData =
                 (ProctoringWindowData) httpSession
                         .getAttribute(ProctoringGUIService.SESSION_ATTR_PROCTORING_DATA);
@@ -136,7 +89,7 @@ public class ProctoringServlet extends HttpServlet {
         resp.setStatus(HttpServletResponse.SC_OK);
     }
 
-    private UserInfo isAuthenticated(
+    private boolean isAuthenticated(
             final HttpSession httpSession,
             final WebApplicationContext webApplicationContext) {
 
@@ -144,11 +97,7 @@ public class ProctoringServlet extends HttpServlet {
                 .getBean(AuthorizationContextHolder.class);
         final SEBServerAuthorizationContext authorizationContext = authorizationContextHolder
                 .getAuthorizationContext(httpSession);
-        if (!authorizationContext.isValid() || !authorizationContext.isLoggedIn()) {
-            throw new RuntimeException("No authentication found");
-        }
-
-        return authorizationContext.getLoggedInUser().getOrThrow();
+        return authorizationContext.isValid() && authorizationContext.isLoggedIn();
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ScreenProctoringSettingsPopup.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ScreenProctoringSettingsPopup.java
index 5cf42840..dddbc0db 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ScreenProctoringSettingsPopup.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/exam/ScreenProctoringSettingsPopup.java
@@ -199,7 +199,13 @@ public class ScreenProctoringSettingsPopup {
                     new ActionEvent(action),
                     action.pageContext());
             return true;
+        } else {
+            final String bundled = formHandle.getForm().getStaticValue(ScreenProctoringSettings.ATTR_SPS_BUNDLED);
+            if (bundled != null) {
+                pageContext.notifyActivationError(EntityType.SCREEN_PROCTORING_GROUP, saveRequest.getError());
+            }
         }
+
         return false;
     }
 
@@ -243,11 +249,14 @@ public class ScreenProctoringSettingsPopup {
                     this.pageContext.getAttribute(PageContext.AttributeKeys.FORCE_READ_ONLY));
 
             final FormHandle form = this.pageService.formBuilder(formContext)
+                    .putStaticValueIf(
+                            () -> settings.bundled,
+                            ScreenProctoringSettings.ATTR_SPS_BUNDLED,
+                            Constants.TRUE_STRING)
                     .withDefaultSpanInput(5)
                     .withEmptyCellSeparation(true)
                     .withDefaultSpanEmptyCell(1)
                     .readonly(isReadonly)
-
                     .addField(FormBuilder.text(
                             "Info",
                             FORM_INFO_TITLE,
@@ -265,33 +274,39 @@ public class ScreenProctoringSettingsPopup {
                             ScreenProctoringSettings.ATTR_SPS_SERVICE_URL,
                             FORM_URL,
                             settings.spsServiceURL)
-                            .mandatory())
+                            .mandatory()
+                            .readonly(settings.bundled))
 
                     .addField(FormBuilder.text(
                             ScreenProctoringSettings.ATTR_SPS_API_KEY,
                             FORM_APPKEY_SPS,
-                            settings.spsAPIKey))
+                            settings.spsAPIKey)
+                            .readonly(settings.bundled))
                     .withEmptyCellSeparation(false)
 
-                    .addField(FormBuilder.password(
-                            ScreenProctoringSettings.ATTR_SPS_API_SECRET,
-                            FORM_APPSECRET_SPS,
-                            (settings.spsAPISecret != null)
-                                    ? String.valueOf(settings.spsAPISecret)
-                                    : null))
+                    .addFieldIf(
+                            () -> !settings.bundled,
+                            () -> FormBuilder.password(
+                                    ScreenProctoringSettings.ATTR_SPS_API_SECRET,
+                                    FORM_APPSECRET_SPS,
+                                    (settings.spsAPISecret != null)
+                                            ? String.valueOf(settings.spsAPISecret)
+                                            : null))
 
                     .addField(FormBuilder.text(
                             ScreenProctoringSettings.ATTR_SPS_ACCOUNT_ID,
                             FORM_ACCOUNT_ID_SPS,
-                            settings.spsAccountId))
+                            settings.spsAccountId)
+                            .readonly(settings.bundled))
                     .withEmptyCellSeparation(false)
-
-                    .addField(FormBuilder.password(
-                            ScreenProctoringSettings.ATTR_SPS_ACCOUNT_PASSWORD,
-                            FORM_ACCOUNT_SECRET_SPS,
-                            (settings.spsAccountPassword != null)
-                                    ? String.valueOf(settings.spsAccountPassword)
-                                    : null))
+                    .addFieldIf(
+                            () -> !settings.bundled,
+                            () -> FormBuilder.password(
+                                    ScreenProctoringSettings.ATTR_SPS_ACCOUNT_PASSWORD,
+                                    FORM_ACCOUNT_SECRET_SPS,
+                                    (settings.spsAccountPassword != null)
+                                            ? String.valueOf(settings.spsAccountPassword)
+                                            : null))
 
                     .build();
 
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/Form.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/Form.java
index 3e4a6a57..af133611 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/form/Form.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/Form.java
@@ -108,6 +108,10 @@ public final class Form implements FormBinding {
         }
     }
 
+    public String getStaticValue(final String name) {
+        return this.staticValues.get(name);
+    }
+
     public void addToGroup(final String groupName, final String fieldName) {
         if (this.formFields.containsKey(fieldName)) {
             this.groups.computeIfAbsent(groupName, k -> new HashSet<>())
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/OAuth2AuthorizationContextHolder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/OAuth2AuthorizationContextHolder.java
index 29b160de..6a720e11 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/OAuth2AuthorizationContextHolder.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/OAuth2AuthorizationContextHolder.java
@@ -212,6 +212,14 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol
             return true;
         }
 
+        @Override
+        public CharSequence getUserPassword() {
+            if (isLoggedIn()) {
+                return this.resource.getPassword();
+            }
+            return null;
+        }
+
         @Override
         public boolean login(final String username, final CharSequence password) {
             if (!this.valid || this.isLoggedIn()) {
@@ -363,6 +371,5 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol
                 }
             }
         }
-
     }
 }
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/SEBServerAuthorizationContext.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/SEBServerAuthorizationContext.java
index 7db177c2..292f25b0 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/SEBServerAuthorizationContext.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/SEBServerAuthorizationContext.java
@@ -63,4 +63,6 @@ public interface SEBServerAuthorizationContext {
      * @return the underling RestTemplate to connect and communicate with the SEB Server webservice */
     RestTemplate getRestTemplate();
 
+    CharSequence getUserPassword();
+
 }
diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/MonitoringProctoringService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/MonitoringProctoringService.java
index 131ffda5..491e6b1f 100644
--- a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/MonitoringProctoringService.java
+++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/proctoring/MonitoringProctoringService.java
@@ -27,7 +27,10 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.core.io.Resource;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
@@ -47,10 +50,10 @@ import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
 import ch.ethz.seb.sebserver.gbl.model.session.RemoteProctoringRoom;
 import ch.ethz.seb.sebserver.gbl.model.session.ScreenProctoringGroup;
 import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
+import ch.ethz.seb.sebserver.gbl.util.Cryptor;
 import ch.ethz.seb.sebserver.gbl.util.Tuple;
 import ch.ethz.seb.sebserver.gbl.util.Utils;
 import ch.ethz.seb.sebserver.gui.GuiServiceInfo;
-import ch.ethz.seb.sebserver.gui.ProctoringServlet;
 import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
 import ch.ethz.seb.sebserver.gui.content.action.ActionPane;
 import ch.ethz.seb.sebserver.gui.content.monitoring.ProctorRoomConnectionsPopup;
@@ -98,16 +101,16 @@ public class MonitoringProctoringService {
     private final JSONMapper jsonMapper;
     private final Resource openRoomScriptRes;
     private final String remoteProctoringEndpoint;
-    private final String remoteProctoringViewServletEndpoint;
+    private final Cryptor cryptor;
 
     public MonitoringProctoringService(
             final PageService pageService,
             final GuiServiceInfo guiServiceInfo,
             final ProctorRoomConnectionsPopup proctorRoomConnectionsPopup,
             final JSONMapper jsonMapper,
+            final Cryptor cryptor,
             @Value(OPEN_ROOM_SCRIPT_RES) final Resource openRoomScript,
-            @Value("${sebserver.gui.remote.proctoring.entrypoint:/remote-proctoring}") final String remoteProctoringEndpoint,
-            @Value("${sebserver.gui.remote.proctoring.api-servler.endpoint:/remote-view-servlet}") final String remoteProctoringViewServletEndpoint) {
+            @Value("${sebserver.gui.remote.proctoring.entrypoint:/remote-proctoring}") final String remoteProctoringEndpoint) {
 
         this.pageService = pageService;
         this.guiServiceInfo = guiServiceInfo;
@@ -115,7 +118,7 @@ public class MonitoringProctoringService {
         this.jsonMapper = jsonMapper;
         this.openRoomScriptRes = openRoomScript;
         this.remoteProctoringEndpoint = remoteProctoringEndpoint;
-        this.remoteProctoringViewServletEndpoint = remoteProctoringViewServletEndpoint;
+        this.cryptor = cryptor;
     }
 
     public boolean isTownhallRoomActive(final String examModelId) {
@@ -314,34 +317,55 @@ public class MonitoringProctoringService {
             final ScreenProctoringGroup group,
             final PageAction _action) {
 
-        // TODO make this configurable or static
-        final String serviceRedirect = settings.spsServiceURL + "/gui-redirect-location";
-        final ResponseEntity redirect = new RestTemplate().exchange(
-                serviceRedirect,
-                HttpMethod.GET,
-                null,
-                String.class);
+        try {
+            // Get login Token for user login from SPS service
+            final RestTemplate restTemplate = new RestTemplate();
+            final String serviceRedirect = settings.spsServiceURL + "/gui-redirect-location";
+            final ResponseEntity redirect = restTemplate.exchange(
+                    serviceRedirect,
+                    HttpMethod.GET,
+                    null,
+                    String.class);
 
-        final String redirectLocation = redirect.getBody();
-        final CurrentUser currentUser = this.pageService.getCurrentUser();
+            // JWT token request URL
+            final String jwtTokenURL = settings.spsServiceURL + API.OAUTH_JWTTOKEN_ENDPOINT;
 
-        ProctoringGUIService.setCurrentScreenProctoringWindowData(
-                group.uuid,
-                redirectLocation,
-                currentUser.get().username,
-                "admin");
+            // Basic Auth header and content type header
+            final HttpHeaders httpHeaders = new HttpHeaders();
+            httpHeaders.add(
+                    HttpHeaders.AUTHORIZATION,
+                    Utils.createBasicAuthHeader(
+                            settings.spsAPIKey,
+                            this.cryptor.decrypt(settings.getSpsAPISecret()).getOrThrow()));
+            httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
 
-        final UrlLauncher launcher = RWT.getClient().getService(UrlLauncher.class);
-        final String url = this.guiServiceInfo.getExternalServerURIBuilder().toUriString()
-                + this.remoteProctoringEndpoint
-                + this.remoteProctoringViewServletEndpoint
-                + Constants.SLASH
-                + Constants.QUERY
-                + ProctoringServlet.SCREEN_PROCOTRING_FLAG_PARAM
-                + Constants.EQUALITY_SIGN
-                + Constants.TRUE_STRING;
+            // user credential and redirect info for jwt token request in body - form URL encoded format
+            final CurrentUser currentUser = this.pageService.getCurrentUser();
+            final CharSequence userPassword = currentUser
+                    .getAuthorizationContextHolder()
+                    .getAuthorizationContext()
+                    .getUserPassword();
+            final String body = "username=" + currentUser.get().username
+                    + "&password=" + userPassword.toString()
+                    + "&redirect=/galleryView/" + group.uuid;
 
-        launcher.openURL(url);
+            // apply jwt token request
+            final HttpEntity httpEntity = new HttpEntity<>(body, httpHeaders);
+            final ResponseEntity tokenRequest = restTemplate.exchange(
+                    jwtTokenURL,
+                    HttpMethod.POST,
+                    httpEntity,
+                    String.class);
+
+            // Open SPS Gui redirect URL with login token (jwt token) in new browser tab
+            final String redirectLocation = redirect.getBody() + "/jwt?token=" + tokenRequest.getBody();
+            final UrlLauncher launcher = RWT.getClient().getService(UrlLauncher.class);
+            launcher.openURL(redirectLocation);
+        } catch (final Exception e) {
+            log.error("Failed to open screen proctoring service group gallery view: ", e);
+            _action.pageContext()
+                    .notifyError(new LocTextKey("Failed to open screen proctoring service group gallery view"), e);
+        }
         return _action;
     }
 
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceInfo.java b/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceInfo.java
index 340cca32..26976b85 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceInfo.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceInfo.java
@@ -30,6 +30,7 @@ import org.springframework.web.util.UriComponentsBuilder;
 
 import ch.ethz.seb.sebserver.gbl.Constants;
 import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
+import ch.ethz.seb.sebserver.gbl.util.Cryptor;
 import ch.ethz.seb.sebserver.webservice.servicelayer.dao.WebserviceInfoDAO;
 
 @Lazy
@@ -80,9 +81,12 @@ public class WebserviceInfo {
     @Value("${sebserver.webservice.api.exam.accessTokenValiditySeconds:43200}")
     private int examAPITokenValiditySeconds;
 
+    private final ScreenProctoringServiceBundle screenProctoringServiceBundle;
+
     public WebserviceInfo(
             final WebserviceInfoDAO webserviceInfoDAO,
-            final Environment environment) {
+            final Environment environment,
+            final Cryptor cryptor) {
 
         this.webserviceInfoDAO = webserviceInfoDAO;
         this.sebServerVersion = environment.getRequiredProperty(VERSION_KEY);
@@ -145,6 +149,24 @@ public class WebserviceInfo {
         } else {
             this.lmsExternalAddressAlias = Collections.emptyMap();
         }
+
+        final boolean spsBundled = BooleanUtils.toBoolean(environment.getProperty(
+                "sebserver.feature.seb.screenProctoring.bundled",
+                Constants.FALSE_STRING));
+        if (spsBundled) {
+            this.screenProctoringServiceBundle = new ScreenProctoringServiceBundle(
+                    environment.getProperty("sebserver.feature.seb.screenProctoring.bundled.url"),
+                    environment.getProperty("sebserver.feature.seb.screenProctoring.bundled.clientId"),
+                    cryptor.encrypt(
+                            environment.getProperty("sebserver.feature.seb.screenProctoring.bundled.clientPassword"))
+                            .getOrThrow(),
+                    environment.getProperty("sebserver.feature.seb.screenProctoring.bundled.sebserveraccount.username"),
+                    cryptor.encrypt(environment
+                            .getProperty("sebserver.feature.seb.screenProctoring.bundled.sebserveraccount.password"))
+                            .getOrThrow());
+        } else {
+            this.screenProctoringServiceBundle = new ScreenProctoringServiceBundle();
+        }
     }
 
     public boolean isMaster() {
@@ -207,6 +229,10 @@ public class WebserviceInfo {
         return this.distributedUpdateInterval;
     }
 
+    public ScreenProctoringServiceBundle getScreenProctoringServiceBundle() {
+        return this.screenProctoringServiceBundle;
+    }
+
     public String getLocalHostName() {
         try {
             return InetAddress.getLocalHost().getHostName();
@@ -300,4 +326,53 @@ public class WebserviceInfo {
         return builder.toString();
     }
 
+    public static final class ScreenProctoringServiceBundle {
+
+        public final boolean bundled;
+        public final String serviceURL;
+        public final String clientId;
+        public final CharSequence clientSecret;
+        public final String apiAccountName;
+        public final CharSequence apiAccountPassword;
+
+        public ScreenProctoringServiceBundle(
+                final String serviceURL,
+                final String clientId,
+                final CharSequence clientSecret,
+                final String apiAccountName,
+                final CharSequence apiAccountPassword) {
+
+            this.bundled = true;
+            this.serviceURL = serviceURL;
+            this.clientId = clientId;
+            this.clientSecret = clientSecret;
+            this.apiAccountName = apiAccountName;
+            this.apiAccountPassword = apiAccountPassword;
+        }
+
+        public ScreenProctoringServiceBundle() {
+            this.bundled = false;
+            this.serviceURL = null;
+            this.clientId = null;
+            this.clientSecret = null;
+            this.apiAccountName = null;
+            this.apiAccountPassword = null;
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder builder = new StringBuilder();
+            builder.append("ScreenProctoringServiceBundle [bundled=");
+            builder.append(this.bundled);
+            builder.append(", serviceURL=");
+            builder.append(this.serviceURL);
+            builder.append(", clientId=");
+            builder.append(this.clientId);
+            builder.append(", apiAccountName=");
+            builder.append(this.apiAccountName);
+            builder.append("]");
+            return builder.toString();
+        }
+    }
+
 }
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceInit.java b/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceInit.java
index b6f9c046..31723aa5 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceInit.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/WebserviceInit.java
@@ -22,8 +22,8 @@ import org.springframework.stereotype.Component;
 import ch.ethz.seb.sebserver.SEBServerInit;
 import ch.ethz.seb.sebserver.SEBServerInitEvent;
 import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
+import ch.ethz.seb.sebserver.webservice.WebserviceInfo.ScreenProctoringServiceBundle;
 import ch.ethz.seb.sebserver.webservice.servicelayer.dao.WebserviceInfoDAO;
-import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.SEBClientPingServiceFactory;
 
 @Component
 @WebServiceProfile
@@ -39,7 +39,6 @@ public class WebserviceInit implements ApplicationListener ");
         SEBServerInit.INIT_LOGGER.info("----> Working with ping service: {}",
-                this.sebClientPingServiceFactory.getWorkingServiceType());
+                this.environment.getProperty("sebserver.webservice.ping.service.strategy"));
 
         SEBServerInit.INIT_LOGGER.info("----> ");
         SEBServerInit.INIT_LOGGER.info("----> Server address: {}", this.environment.getProperty("server.address"));
@@ -153,6 +150,14 @@ public class WebserviceInit implements ApplicationListener admin API refresh token validity: " + this.webserviceInfo.getAdminRefreshTokenValSec() + "s");
         SEBServerInit.INIT_LOGGER.info(
                 "----> exam API access token validity: " + this.webserviceInfo.getExamAPITokenValiditySeconds() + "s");
+
+        final ScreenProctoringServiceBundle spsBundle = this.webserviceInfo.getScreenProctoringServiceBundle();
+        SEBServerInit.INIT_LOGGER.info("----> ");
+        SEBServerInit.INIT_LOGGER.info("----> Screen Proctoring Bundle enabled: {}", spsBundle.bundled);
+        if (spsBundle.bundled) {
+            SEBServerInit.INIT_LOGGER.info("------> {}", spsBundle);
+        }
+
         SEBServerInit.INIT_LOGGER.info("----> ");
         SEBServerInit.INIT_LOGGER.info("----> Property Override Test: {}", this.webserviceInfo.getTestProperty());
 
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ProctoringSettingsDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ProctoringSettingsDAO.java
index 011ccaa5..d20d7b9d 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ProctoringSettingsDAO.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ProctoringSettingsDAO.java
@@ -21,7 +21,7 @@ public interface ProctoringSettingsDAO {
             EntityKey entityKey,
             ProctoringServiceSettings proctoringServiceSettings);
 
-    Result getScreenProctoringSettings(EntityKey entityKey);
+    Result getScreenProctoringSettings(EntityKey entityKeyp);
 
     Result storeScreenProctoringSettings(
             final EntityKey entityKey,
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/ProctoringAdminServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/ProctoringAdminServiceImpl.java
index 240cd90a..7ea720de 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/ProctoringAdminServiceImpl.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/exam/impl/ProctoringAdminServiceImpl.java
@@ -18,7 +18,10 @@ import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
 import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings.ProctoringServerType;
 import ch.ethz.seb.sebserver.gbl.model.exam.ScreenProctoringSettings;
 import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
+import ch.ethz.seb.sebserver.gbl.util.Cryptor;
 import ch.ethz.seb.sebserver.gbl.util.Result;
+import ch.ethz.seb.sebserver.webservice.WebserviceInfo;
+import ch.ethz.seb.sebserver.webservice.WebserviceInfo.ScreenProctoringServiceBundle;
 import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ProctoringSettingsDAO;
 import ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl.ProctoringSettingsDAOImpl;
 import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ProctoringAdminService;
@@ -36,17 +39,23 @@ public class ProctoringAdminServiceImpl implements ProctoringAdminService {
     private final RemoteProctoringServiceFactory remoteProctoringServiceFactory;
     private final ScreenProctoringService screenProctoringService;
     private final ExamSessionCacheService examSessionCacheService;
+    private final ScreenProctoringServiceBundle screenProctoringServiceBundle;
+    private final Cryptor cryptor;
 
     public ProctoringAdminServiceImpl(
             final ProctoringSettingsDAOImpl proctoringSettingsDAO,
             final RemoteProctoringServiceFactory remoteProctoringServiceFactory,
             final ScreenProctoringService screenProctoringService,
-            final ExamSessionCacheService examSessionCacheService) {
+            final ExamSessionCacheService examSessionCacheService,
+            final WebserviceInfo webserviceInfo,
+            final Cryptor cryptor) {
 
         this.proctoringSettingsDAO = proctoringSettingsDAO;
         this.remoteProctoringServiceFactory = remoteProctoringServiceFactory;
         this.screenProctoringService = screenProctoringService;
         this.examSessionCacheService = examSessionCacheService;
+        this.screenProctoringServiceBundle = webserviceInfo.getScreenProctoringServiceBundle();
+        this.cryptor = cryptor;
     }
 
     @Override
@@ -91,9 +100,25 @@ public class ProctoringAdminServiceImpl implements ProctoringAdminService {
 
             checkType(parentEntityKey);
 
-            return this.proctoringSettingsDAO
+            ScreenProctoringSettings settings = this.proctoringSettingsDAO
                     .getScreenProctoringSettings(parentEntityKey)
                     .getOrThrow();
+
+            if (this.screenProctoringServiceBundle.bundled) {
+                settings = new ScreenProctoringSettings(
+                        settings.examId,
+                        settings.enableScreenProctoring,
+                        this.screenProctoringServiceBundle.serviceURL,
+                        this.screenProctoringServiceBundle.clientId,
+                        null,
+                        this.screenProctoringServiceBundle.apiAccountName,
+                        null,
+                        settings.collectingStrategy,
+                        settings.collectingGroupSize,
+                        true);
+            }
+
+            return settings;
         });
     }
 
@@ -106,17 +131,30 @@ public class ProctoringAdminServiceImpl implements ProctoringAdminService {
 
             checkType(parentEntityKey);
 
+            ScreenProctoringSettings settings = screenProctoringSettings;
+            if (this.screenProctoringServiceBundle.bundled) {
+                settings = new ScreenProctoringSettings(
+                        screenProctoringSettings.examId,
+                        screenProctoringSettings.enableScreenProctoring,
+                        this.screenProctoringServiceBundle.serviceURL,
+                        this.screenProctoringServiceBundle.clientId,
+                        this.cryptor.decrypt(this.screenProctoringServiceBundle.clientSecret).getOrThrow(),
+                        this.screenProctoringServiceBundle.apiAccountName,
+                        this.cryptor.decrypt(this.screenProctoringServiceBundle.apiAccountPassword).getOrThrow(),
+                        screenProctoringSettings.collectingStrategy,
+                        screenProctoringSettings.collectingGroupSize,
+                        true);
+            }
+
             this.screenProctoringService
-                    .testSettings(screenProctoringSettings)
-                    .flatMap(settings -> this.proctoringSettingsDAO.storeScreenProctoringSettings(
-                            parentEntityKey,
-                            screenProctoringSettings))
+                    .testSettings(settings)
+                    .flatMap(s -> this.proctoringSettingsDAO.storeScreenProctoringSettings(parentEntityKey, s))
                     .getOrThrow();
 
             if (parentEntityKey.entityType == EntityType.EXAM) {
 
                 this.screenProctoringService
-                        .applyScreenProctoingForExam(screenProctoringSettings.examId)
+                        .applyScreenProctoingForExam(settings.examId)
                         .onError(error -> this.proctoringSettingsDAO
                                 .disableScreenProctoring(screenProctoringSettings.examId))
                         .getOrThrow();
@@ -128,7 +166,7 @@ public class ProctoringAdminServiceImpl implements ProctoringAdminService {
                 }
             }
 
-            return screenProctoringSettings;
+            return settings;
         });
     }
 
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientPingBatchService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientPingBatchService.java
index 804c75e6..bb723318 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientPingBatchService.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientPingBatchService.java
@@ -21,6 +21,7 @@ import org.ehcache.impl.internal.concurrent.ConcurrentHashMap;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
 import org.springframework.stereotype.Component;
@@ -33,6 +34,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientPingServic
 @Lazy
 @Component
 @WebServiceProfile
+@ConditionalOnExpression("'${sebserver.webservice.ping.service.strategy}'.equals('BATCH')")
 public class SEBClientPingBatchService implements SEBClientPingService {
 
     private static final Logger log = LoggerFactory.getLogger(SEBClientPingBatchService.class);
@@ -116,9 +118,9 @@ public class SEBClientPingBatchService implements SEBClientPingService {
                     + this.instructions);
             this.pings.put(connectionToken, instructionConfirm);
 //            // TODO is this a good idea or is there another better way to deal with instruction confirm synchronization?
-//            if (instruction != null && instruction.contains("\"instruction-confirm\":\"" + instructionConfirm + "\"")) {
-//                return null;
-//            }
+            if (instruction != null && instruction.contains("\"instruction-confirm\":\"" + instructionConfirm + "\"")) {
+                return null;
+            }
         } else if (!this.pings.containsKey(connectionToken)) {
             this.pings.put(connectionToken, StringUtils.EMPTY);
         }
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientPingBlockingService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientPingBlockingService.java
index 3d5c451a..471f8928 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientPingBlockingService.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientPingBlockingService.java
@@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Component;
 
@@ -22,6 +23,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientPingServic
 @Lazy
 @Component
 @WebServiceProfile
+@ConditionalOnExpression("'${sebserver.webservice.ping.service.strategy}'.equals('BLOCKING')")
 public class SEBClientPingBlockingService implements SEBClientPingService {
 
     private static final Logger log = LoggerFactory.getLogger(SEBClientPingBlockingService.class);
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientPingServiceFactory.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientPingServiceFactory.java
deleted file mode 100644
index 31cd6ea7..00000000
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientPingServiceFactory.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2023 ETH Zürich, Educational Development and Technology (LET)
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
-
-import java.util.Collection;
-import java.util.EnumMap;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-
-import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
-import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientPingService;
-
-@Lazy
-@Component
-@WebServiceProfile
-public class SEBClientPingServiceFactory {
-
-    private static final Logger log = LoggerFactory.getLogger(SEBClientPingServiceFactory.class);
-
-    private final EnumMap serviceMapping =
-            new EnumMap<>(SEBClientPingService.PingServiceType.class);
-    private final SEBClientPingService.PingServiceType workingServiceType;
-
-    public SEBClientPingServiceFactory(
-            final Collection serviceBeans,
-            @Value("${sebserver.webservice.api.exam.session.ping.service.strategy:BLOCKING}") final String serviceType) {
-
-        SEBClientPingService.PingServiceType serviceTypeToSet = SEBClientPingService.PingServiceType.BLOCKING;
-        try {
-            serviceTypeToSet = SEBClientPingService.PingServiceType.valueOf(serviceType);
-        } catch (final Exception e) {
-            serviceTypeToSet = SEBClientPingService.PingServiceType.BLOCKING;
-        }
-        this.workingServiceType = serviceTypeToSet;
-
-        serviceBeans.stream().forEach(service -> this.serviceMapping.putIfAbsent(service.pingServiceType(), service));
-    }
-
-    public SEBClientPingService.PingServiceType getWorkingServiceType() {
-        return this.workingServiceType;
-    }
-
-    public SEBClientPingService getSEBClientPingService() {
-
-        log.info("Work with SEBClientPingService of type: {}", this.workingServiceType);
-
-        switch (this.workingServiceType) {
-            case BATCH: {
-                final SEBClientPingService service =
-                        this.serviceMapping.get(SEBClientPingService.PingServiceType.BATCH);
-                if (service != null) {
-                    ((SEBClientPingBatchService) service).init();
-                    return service;
-                } else {
-                    return this.serviceMapping.get(SEBClientPingService.PingServiceType.BLOCKING);
-                }
-            }
-            default:
-                return this.serviceMapping.get(SEBClientPingService.PingServiceType.BLOCKING);
-        }
-    }
-
-}
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientSessionServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientSessionServiceImpl.java
index 9d668706..2c34a1be 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientSessionServiceImpl.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientSessionServiceImpl.java
@@ -60,7 +60,7 @@ public class SEBClientSessionServiceImpl implements SEBClientSessionService {
             final InternalClientConnectionDataFactory internalClientConnectionDataFactory,
             final SecurityKeyService securityKeyService,
             final SEBClientVersionService sebClientVersionService,
-            final SEBClientPingServiceFactory sebClientPingServiceFactory) {
+            final SEBClientPingService sebClientPingService) {
 
         this.clientConnectionDAO = clientConnectionDAO;
         this.examSessionService = examSessionService;
@@ -70,7 +70,7 @@ public class SEBClientSessionServiceImpl implements SEBClientSessionService {
         this.internalClientConnectionDataFactory = internalClientConnectionDataFactory;
         this.securityKeyService = securityKeyService;
         this.sebClientVersionService = sebClientVersionService;
-        this.sebClientPingService = sebClientPingServiceFactory.getSEBClientPingService();
+        this.sebClientPingService = sebClientPingService;
     }
 
     @Override
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ScreenProctoringAPIBinding.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ScreenProctoringAPIBinding.java
index b041355b..3c57d397 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ScreenProctoringAPIBinding.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/proctoring/ScreenProctoringAPIBinding.java
@@ -223,6 +223,10 @@ class ScreenProctoringAPIBinding {
 
                 if (result.getStatusCode() != HttpStatus.OK) {
                     if (result.getStatusCode().is4xxClientError()) {
+                        log.warn(
+                                "Failed to establish REST connection to: {}. status: {}",
+                                screenProctoringSettings.spsServiceURL, result.getStatusCode());
+
                         throw new FieldValidationException(
                                 "serverURL",
                                 "screenProctoringSettings:spsServiceURL:url.noAccess");
@@ -302,7 +306,6 @@ class ScreenProctoringAPIBinding {
                 final SPSData spsData = this.getSPSData(exam.id);
                 // re-activate all needed entities on SPS side
                 activation(exam, SPS_API.SEB_ACCESS_ENDPOINT, spsData.spsSEBAccesUUID, true, apiTemplate);
-                activation(exam, SPS_API.EXAM_ENDPOINT, spsData.spsExamUUID, true, apiTemplate);
 
                 // mark successfully activated on SPS side
                 this.additionalAttributesDAO.saveAdditionalAttribute(
@@ -367,7 +370,7 @@ class ScreenProctoringAPIBinding {
             final ScreenProctoringServiceOAuthTemplate apiTemplate = this.getAPITemplate(exam.id);
 
             final String uri = UriComponentsBuilder
-                    .fromUriString(this.apiTemplate.screenProctoringSettings.spsServiceURL)
+                    .fromUriString(apiTemplate.screenProctoringSettings.spsServiceURL)
                     .path(SPS_API.EXAM_ENDPOINT)
                     .pathSegment(spsData.spsExamUUID)
                     .build()
@@ -410,8 +413,8 @@ class ScreenProctoringAPIBinding {
             }
 
             final SPSData spsData = this.getSPSData(exam.id);
-            activation(exam, SPS_API.EXAM_ENDPOINT, spsData.spsExamUUID, false, this.apiTemplate);
-            activation(exam, SPS_API.SEB_ACCESS_ENDPOINT, spsData.spsSEBAccesUUID, false, this.apiTemplate);
+            final ScreenProctoringServiceOAuthTemplate apiTemplate = this.getAPITemplate(exam.id);
+            activation(exam, SPS_API.SEB_ACCESS_ENDPOINT, spsData.spsSEBAccesUUID, false, apiTemplate);
 
             // mark successfully dispose on SPS side
             this.additionalAttributesDAO.saveAdditionalAttribute(
@@ -490,7 +493,7 @@ class ScreenProctoringAPIBinding {
         final String token = clientConnection.getConnectionToken();
         final ScreenProctoringServiceOAuthTemplate apiTemplate = this.getAPITemplate(examId);
         final String uri = UriComponentsBuilder
-                .fromUriString(this.apiTemplate.screenProctoringSettings.spsServiceURL)
+                .fromUriString(apiTemplate.screenProctoringSettings.spsServiceURL)
                 .path(SPS_API.SESSION_ENDPOINT)
 
                 .build()
@@ -567,7 +570,7 @@ class ScreenProctoringAPIBinding {
                     userInfo.roles);
 
             final String uri = UriComponentsBuilder
-                    .fromUriString(this.apiTemplate.screenProctoringSettings.spsServiceURL)
+                    .fromUriString(apiTemplate.screenProctoringSettings.spsServiceURL)
                     .path(SPS_API.USERSYNC_SEBSERVER_ENDPOINT)
                     .build()
                     .toUriString();
@@ -603,7 +606,7 @@ class ScreenProctoringAPIBinding {
                     .getOrThrow();
 
             final String uri = UriComponentsBuilder
-                    .fromUriString(this.apiTemplate.screenProctoringSettings.spsServiceURL)
+                    .fromUriString(apiTemplate.screenProctoringSettings.spsServiceURL)
                     .path(SPS_API.ENTIY_PRIVILEGES_ENDPOINT)
                     .build()
                     .toUriString();
@@ -696,7 +699,7 @@ class ScreenProctoringAPIBinding {
             throws JsonMappingException, JsonProcessingException {
 
         final String uri = UriComponentsBuilder
-                .fromUriString(this.apiTemplate.screenProctoringSettings.spsServiceURL)
+                .fromUriString(apiTemplate.screenProctoringSettings.spsServiceURL)
                 .path(SPS_API.GROUP_ENDPOINT)
                 .build()
                 .toUriString();
@@ -729,7 +732,7 @@ class ScreenProctoringAPIBinding {
         try {
 
             final String uri = UriComponentsBuilder
-                    .fromUriString(this.apiTemplate.screenProctoringSettings.spsServiceURL)
+                    .fromUriString(apiTemplate.screenProctoringSettings.spsServiceURL)
                     .path(SPS_API.EXAM_ENDPOINT)
                     .build().toUriString();
 
@@ -773,7 +776,7 @@ class ScreenProctoringAPIBinding {
             final String description = "This SEB access was auto-generated by SEB Server";
 
             final String uri = UriComponentsBuilder
-                    .fromUriString(this.apiTemplate.screenProctoringSettings.spsServiceURL)
+                    .fromUriString(apiTemplate.screenProctoringSettings.spsServiceURL)
                     .path(SPS_API.SEB_ACCESS_ENDPOINT)
                     .build()
                     .toUriString();
@@ -816,7 +819,7 @@ class ScreenProctoringAPIBinding {
         try {
 
             final String uri = UriComponentsBuilder
-                    .fromUriString(this.apiTemplate.screenProctoringSettings.spsServiceURL)
+                    .fromUriString(apiTemplate.screenProctoringSettings.spsServiceURL)
                     .path(domainPath)
                     .pathSegment(uuid)
                     .pathSegment(activate ? SPS_API.ACTIVE_PATH_SEGMENT : SPS_API.INACTIVE_PATH_SEGMENT)
@@ -840,7 +843,7 @@ class ScreenProctoringAPIBinding {
         try {
 
             final String uri = UriComponentsBuilder
-                    .fromUriString(this.apiTemplate.screenProctoringSettings.spsServiceURL)
+                    .fromUriString(apiTemplate.screenProctoringSettings.spsServiceURL)
                     .path(domainPath)
                     .pathSegment(uuid)
                     .build()
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/APIExceptionHandler.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/APIExceptionHandler.java
index 7e47c800..2ccf8d5d 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/APIExceptionHandler.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/APIExceptionHandler.java
@@ -14,6 +14,7 @@ import java.util.List;
 import java.util.concurrent.CompletionException;
 import java.util.stream.Collectors;
 
+import org.apache.catalina.connector.ClientAbortException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.core.Ordered;
@@ -281,4 +282,14 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler {
 
     }
 
+    @ExceptionHandler(ClientAbortException.class)
+    public ResponseEntity