Search in sources :

Example 1 with DefaultErrorResponse

use of io.jans.as.model.error.DefaultErrorResponse in project jans by JanssenProject.

the class BackchannelAuthorizeRestWebServiceImpl method requestBackchannelAuthorizationPost.

@Override
public Response requestBackchannelAuthorizationPost(String clientId, String scope, String clientNotificationToken, String acrValues, String loginHintToken, String idTokenHint, String loginHint, String bindingMessage, String userCodeParam, Integer requestedExpiry, String request, String requestUri, HttpServletRequest httpRequest, HttpServletResponse httpResponse, SecurityContext securityContext) {
    // it may be encoded
    scope = ServerUtil.urlDecode(scope);
    OAuth2AuditLog oAuth2AuditLog = new OAuth2AuditLog(ServerUtil.getIpAddress(httpRequest), Action.BACKCHANNEL_AUTHENTICATION);
    oAuth2AuditLog.setClientId(clientId);
    oAuth2AuditLog.setScope(scope);
    // ATTENTION : please do not add more parameter in this debug method because it will not work with Seam 2.2.2.Final,
    // there is limit of 10 parameters (hardcoded), see: org.jboss.seam.core.Interpolator#interpolate
    log.debug("Attempting to request backchannel authorization: " + "clientId = {}, scope = {}, clientNotificationToken = {}, acrValues = {}, loginHintToken = {}, " + "idTokenHint = {}, loginHint = {}, bindingMessage = {}, userCodeParam = {}, requestedExpiry = {}, " + "request= {}", clientId, scope, clientNotificationToken, acrValues, loginHintToken, idTokenHint, loginHint, bindingMessage, userCodeParam, requestedExpiry, request);
    log.debug("Attempting to request backchannel authorization: " + "isSecure = {}", securityContext.isSecure());
    errorResponseFactory.validateComponentEnabled(ComponentType.CIBA);
    Response.ResponseBuilder builder = Response.ok();
    SessionClient sessionClient = identity.getSessionClient();
    Client client = null;
    if (sessionClient != null) {
        client = sessionClient.getClient();
    }
    if (client == null) {
        // 401
        builder = Response.status(Response.Status.UNAUTHORIZED.getStatusCode());
        builder.entity(errorResponseFactory.getErrorAsJson(INVALID_CLIENT));
        return builder.build();
    }
    if (!cibaRequestService.hasCibaCompatibility(client)) {
        // 401
        builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
        builder.entity(errorResponseFactory.getErrorAsJson(INVALID_REQUEST));
        return builder.build();
    }
    List<String> scopes = new ArrayList<>();
    if (StringHelper.isNotEmpty(scope)) {
        Set<String> grantedScopes = scopeChecker.checkScopesPolicy(client, scope);
        scopes.addAll(grantedScopes);
    }
    JwtAuthorizationRequest jwtRequest = null;
    if (StringUtils.isNotBlank(request) || StringUtils.isNotBlank(requestUri)) {
        jwtRequest = JwtAuthorizationRequest.createJwtRequest(request, requestUri, client, null, cryptoProvider, appConfiguration);
        if (jwtRequest == null) {
            log.error("The JWT couldn't be processed");
            // 400
            builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
            builder.entity(errorResponseFactory.getErrorAsJson(INVALID_REQUEST));
            throw new WebApplicationException(builder.build());
        }
        authorizeRestWebServiceValidator.validateCibaRequestObject(jwtRequest, client.getClientId());
        // JWT wins
        if (!jwtRequest.getScopes().isEmpty()) {
            scopes.addAll(scopeChecker.checkScopesPolicy(client, jwtRequest.getScopes()));
        }
        if (StringUtils.isNotBlank(jwtRequest.getClientNotificationToken())) {
            clientNotificationToken = jwtRequest.getClientNotificationToken();
        }
        if (StringUtils.isNotBlank(jwtRequest.getAcrValues())) {
            acrValues = jwtRequest.getAcrValues();
        }
        if (StringUtils.isNotBlank(jwtRequest.getLoginHintToken())) {
            loginHintToken = jwtRequest.getLoginHintToken();
        }
        if (StringUtils.isNotBlank(jwtRequest.getIdTokenHint())) {
            idTokenHint = jwtRequest.getIdTokenHint();
        }
        if (StringUtils.isNotBlank(jwtRequest.getLoginHint())) {
            loginHint = jwtRequest.getLoginHint();
        }
        if (StringUtils.isNotBlank(jwtRequest.getBindingMessage())) {
            bindingMessage = jwtRequest.getBindingMessage();
        }
        if (StringUtils.isNotBlank(jwtRequest.getUserCode())) {
            userCodeParam = jwtRequest.getUserCode();
        }
        if (jwtRequest.getRequestedExpiry() != null) {
            requestedExpiry = jwtRequest.getRequestedExpiry();
        } else if (jwtRequest.getExp() != null) {
            requestedExpiry = Math.toIntExact(jwtRequest.getExp() - System.currentTimeMillis() / 1000);
        }
    }
    if (appConfiguration.isFapi() && jwtRequest == null) {
        // 400
        builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
        builder.entity(errorResponseFactory.getErrorAsJson(INVALID_REQUEST));
        return builder.build();
    }
    User user = null;
    try {
        if (Strings.isNotBlank(loginHint)) {
            // login_hint
            user = userService.getUniqueUserByAttributes(appConfiguration.getBackchannelLoginHintClaims(), loginHint);
        } else if (Strings.isNotBlank(idTokenHint)) {
            // id_token_hint
            AuthorizationGrant authorizationGrant = authorizationGrantList.getAuthorizationGrantByIdToken(idTokenHint);
            if (authorizationGrant == null) {
                // 400
                builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
                builder.entity(errorResponseFactory.getErrorAsJson(UNKNOWN_USER_ID));
                return builder.build();
            }
            user = authorizationGrant.getUser();
        }
        if (Strings.isNotBlank(loginHintToken)) {
            // login_hint_token
            Jwt jwt = Jwt.parse(loginHintToken);
            SignatureAlgorithm algorithm = jwt.getHeader().getSignatureAlgorithm();
            String keyId = jwt.getHeader().getKeyId();
            if (algorithm == null || Strings.isBlank(keyId)) {
                // 400
                builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
                builder.entity(errorResponseFactory.getErrorAsJson(UNKNOWN_USER_ID));
                return builder.build();
            }
            boolean validSignature = false;
            if (algorithm.getFamily() == AlgorithmFamily.RSA) {
                RSAPublicKey publicKey = JwkClient.getRSAPublicKey(client.getJwksUri(), keyId);
                RSASigner rsaSigner = new RSASigner(algorithm, publicKey);
                validSignature = rsaSigner.validate(jwt);
            } else if (algorithm.getFamily() == AlgorithmFamily.EC) {
                ECDSAPublicKey publicKey = JwkClient.getECDSAPublicKey(client.getJwksUri(), keyId);
                ECDSASigner ecdsaSigner = new ECDSASigner(algorithm, publicKey);
                validSignature = ecdsaSigner.validate(jwt);
            }
            if (!validSignature) {
                // 400
                builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
                builder.entity(errorResponseFactory.getErrorAsJson(UNKNOWN_USER_ID));
                return builder.build();
            }
            JSONObject subject = jwt.getClaims().getClaimAsJSON("subject");
            if (subject == null || !subject.has("subject_type") || !subject.has(subject.getString("subject_type"))) {
                // 400
                builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
                builder.entity(errorResponseFactory.getErrorAsJson(UNKNOWN_USER_ID));
                return builder.build();
            }
            String subjectTypeKey = subject.getString("subject_type");
            String subjectTypeValue = subject.getString(subjectTypeKey);
            user = userService.getUniqueUserByAttributes(appConfiguration.getBackchannelLoginHintClaims(), subjectTypeValue);
        }
    } catch (InvalidJwtException e) {
        log.error(e.getMessage(), e);
    } catch (JSONException e) {
        log.error(e.getMessage(), e);
    }
    if (user == null) {
        // 400
        builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
        builder.entity(errorResponseFactory.getErrorAsJson(UNKNOWN_USER_ID));
        return builder.build();
    }
    try {
        String userCode = (String) user.getAttribute("jansBackchannelUsrCode", true, false);
        DefaultErrorResponse cibaAuthorizeParamsValidation = cibaAuthorizeParamsValidatorService.validateParams(scopes, clientNotificationToken, client.getBackchannelTokenDeliveryMode(), loginHintToken, idTokenHint, loginHint, bindingMessage, client.getBackchannelUserCodeParameter(), userCodeParam, userCode, requestedExpiry);
        if (cibaAuthorizeParamsValidation != null) {
            builder = Response.status(cibaAuthorizeParamsValidation.getStatus());
            builder.entity(errorResponseFactory.errorAsJson(cibaAuthorizeParamsValidation.getType(), cibaAuthorizeParamsValidation.getReason()));
            return builder.build();
        }
        String deviceRegistrationToken = (String) user.getAttribute("jansBackchannelDeviceRegistrationTkn", true, false);
        if (deviceRegistrationToken == null) {
            // 401
            builder = Response.status(Response.Status.UNAUTHORIZED.getStatusCode());
            builder.entity(errorResponseFactory.getErrorAsJson(UNAUTHORIZED_END_USER_DEVICE));
            return builder.build();
        }
        int expiresIn = requestedExpiry != null ? requestedExpiry : appConfiguration.getBackchannelAuthenticationResponseExpiresIn();
        Integer interval = client.getBackchannelTokenDeliveryMode() == BackchannelTokenDeliveryMode.PUSH ? null : appConfiguration.getBackchannelAuthenticationResponseInterval();
        long currentTime = new Date().getTime();
        CibaRequestCacheControl cibaRequestCacheControl = new CibaRequestCacheControl(user, client, expiresIn, scopes, clientNotificationToken, bindingMessage, currentTime, acrValues);
        cibaRequestService.save(cibaRequestCacheControl, expiresIn);
        String authReqId = cibaRequestCacheControl.getAuthReqId();
        // Notify End-User to obtain Consent/Authorization
        cibaEndUserNotificationService.notifyEndUser(cibaRequestCacheControl.getScopesAsString(), cibaRequestCacheControl.getAcrValues(), authReqId, deviceRegistrationToken);
        builder.entity(getJSONObject(authReqId, expiresIn, interval).toString(4).replace("\\/", "/"));
        builder.type(MediaType.APPLICATION_JSON_TYPE);
        builder.cacheControl(ServerUtil.cacheControl(true, false));
    } catch (JSONException e) {
        builder = Response.status(400);
        builder.entity(errorResponseFactory.getErrorAsJson(INVALID_REQUEST));
        log.error(e.getMessage(), e);
    } catch (InvalidClaimException e) {
        builder = Response.status(400);
        builder.entity(errorResponseFactory.getErrorAsJson(INVALID_REQUEST));
        log.error(e.getMessage(), e);
    }
    applicationAuditLogger.sendMessage(oAuth2AuditLog);
    return builder.build();
}
Also used : InvalidJwtException(io.jans.as.model.exception.InvalidJwtException) User(io.jans.as.common.model.common.User) WebApplicationException(javax.ws.rs.WebApplicationException) SessionClient(io.jans.as.server.model.session.SessionClient) OAuth2AuditLog(io.jans.as.server.model.audit.OAuth2AuditLog) ArrayList(java.util.ArrayList) CibaRequestCacheControl(io.jans.as.server.model.common.CibaRequestCacheControl) SignatureAlgorithm(io.jans.as.model.crypto.signature.SignatureAlgorithm) InvalidClaimException(io.jans.as.model.exception.InvalidClaimException) RSAPublicKey(io.jans.as.model.crypto.signature.RSAPublicKey) RSASigner(io.jans.as.model.jws.RSASigner) JwtAuthorizationRequest(io.jans.as.server.model.authorize.JwtAuthorizationRequest) JwkClient(io.jans.as.client.JwkClient) Client(io.jans.as.common.model.registration.Client) SessionClient(io.jans.as.server.model.session.SessionClient) DefaultErrorResponse(io.jans.as.model.error.DefaultErrorResponse) AuthorizationGrant(io.jans.as.server.model.common.AuthorizationGrant) ECDSAPublicKey(io.jans.as.model.crypto.signature.ECDSAPublicKey) ECDSASigner(io.jans.as.model.jws.ECDSASigner) Jwt(io.jans.as.model.jwt.Jwt) JSONException(org.json.JSONException) Date(java.util.Date) Response(javax.ws.rs.core.Response) DefaultErrorResponse(io.jans.as.model.error.DefaultErrorResponse) HttpServletResponse(javax.servlet.http.HttpServletResponse) JSONObject(org.json.JSONObject)

Example 2 with DefaultErrorResponse

use of io.jans.as.model.error.DefaultErrorResponse in project jans by JanssenProject.

the class CIBADeviceRegistrationValidatorService method validateParams.

public DefaultErrorResponse validateParams(String idTokenHint, String deviceRegistrationToken) {
    if (Strings.isBlank(deviceRegistrationToken)) {
        DefaultErrorResponse errorResponse = new DefaultErrorResponse();
        // 400
        errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
        errorResponse.setType(INVALID_REQUEST);
        errorResponse.setReason("The device registration token cannot be blank.");
        return errorResponse;
    }
    if (Strings.isBlank(idTokenHint)) {
        DefaultErrorResponse errorResponse = new DefaultErrorResponse();
        // 400
        errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
        errorResponse.setType(UNKNOWN_USER_ID);
        errorResponse.setReason("The id token hint cannot be blank.");
        return errorResponse;
    }
    return null;
}
Also used : DefaultErrorResponse(io.jans.as.model.error.DefaultErrorResponse)

Example 3 with DefaultErrorResponse

use of io.jans.as.model.error.DefaultErrorResponse in project jans by JanssenProject.

the class BackchannelDeviceRegistrationRestWebServiceImpl method requestBackchannelDeviceRegistrationPost.

@Override
public Response requestBackchannelDeviceRegistrationPost(String idTokenHint, String deviceRegistrationToken, HttpServletRequest httpRequest, HttpServletResponse httpResponse, SecurityContext securityContext) {
    OAuth2AuditLog oAuth2AuditLog = new OAuth2AuditLog(ServerUtil.getIpAddress(httpRequest), Action.BACKCHANNEL_DEVICE_REGISTRATION);
    // ATTENTION : please do not add more parameter in this debug method because it will not work with Seam 2.2.2.Final,
    // there is limit of 10 parameters (hardcoded), see: org.jboss.seam.core.Interpolator#interpolate
    log.debug("Attempting to request backchannel device registration: " + "idTokenHint = {}, deviceRegistrationToken = {}, isSecure = {}", idTokenHint, deviceRegistrationToken, securityContext.isSecure());
    errorResponseFactory.validateComponentEnabled(ComponentType.CIBA);
    Response.ResponseBuilder builder = Response.ok();
    DefaultErrorResponse cibaDeviceRegistrationValidation = cibaDeviceRegistrationValidatorService.validateParams(idTokenHint, deviceRegistrationToken);
    if (cibaDeviceRegistrationValidation != null) {
        builder = Response.status(cibaDeviceRegistrationValidation.getStatus());
        builder.entity(errorResponseFactory.errorAsJson(cibaDeviceRegistrationValidation.getType(), cibaDeviceRegistrationValidation.getReason()));
        return builder.build();
    }
    User user = null;
    AuthorizationGrant authorizationGrant = authorizationGrantList.getAuthorizationGrantByIdToken(idTokenHint);
    if (authorizationGrant == null) {
        // 400
        builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
        builder.entity(errorResponseFactory.getErrorAsJson(BackchannelAuthenticationErrorResponseType.UNKNOWN_USER_ID));
        return builder.build();
    }
    user = authorizationGrant.getUser();
    if (user == null) {
        // 400
        builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
        builder.entity(errorResponseFactory.getErrorAsJson(UNKNOWN_USER_ID));
        return builder.build();
    }
    userService.setCustomAttribute(user, "jansBackchannelDeviceRegistrationTkn", deviceRegistrationToken);
    userService.updateUser(user);
    applicationAuditLogger.sendMessage(oAuth2AuditLog);
    return builder.build();
}
Also used : HttpServletResponse(javax.servlet.http.HttpServletResponse) DefaultErrorResponse(io.jans.as.model.error.DefaultErrorResponse) Response(javax.ws.rs.core.Response) User(io.jans.as.common.model.common.User) OAuth2AuditLog(io.jans.as.server.model.audit.OAuth2AuditLog) DefaultErrorResponse(io.jans.as.model.error.DefaultErrorResponse) AuthorizationGrant(io.jans.as.server.model.common.AuthorizationGrant)

Example 4 with DefaultErrorResponse

use of io.jans.as.model.error.DefaultErrorResponse in project jans by JanssenProject.

the class CIBAAuthorizeParamsValidatorService method validateParams.

public DefaultErrorResponse validateParams(List<String> scopeList, String clientNotificationToken, BackchannelTokenDeliveryMode tokenDeliveryMode, String loginHintToken, String idTokenHint, String loginHint, String bindingMessage, Boolean backchannelUserCodeParameter, String userCodeParam, String userCode, Integer requestedExpirity) {
    if (tokenDeliveryMode == null) {
        DefaultErrorResponse errorResponse = new DefaultErrorResponse();
        errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
        errorResponse.setType(UNAUTHORIZED_CLIENT);
        errorResponse.setReason("Clients registering to use CIBA must indicate a token delivery mode.");
        return errorResponse;
    }
    if (scopeList == null || !scopeList.contains("openid")) {
        DefaultErrorResponse errorResponse = new DefaultErrorResponse();
        errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
        errorResponse.setType(INVALID_SCOPE);
        errorResponse.setReason("CIBA authentication requests must contain the openid scope value.");
        return errorResponse;
    }
    if (!validateOneParamNotBlank(loginHintToken, idTokenHint, loginHint)) {
        DefaultErrorResponse errorResponse = new DefaultErrorResponse();
        errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
        errorResponse.setType(INVALID_REQUEST);
        errorResponse.setReason("It is required that the Client provides one (and only one) of the hints in the authentication " + "request, that is login_hint_token, id_token_hint or login_hint.");
        return errorResponse;
    }
    if (tokenDeliveryMode == BackchannelTokenDeliveryMode.PING || tokenDeliveryMode == BackchannelTokenDeliveryMode.PUSH) {
        if (Strings.isBlank(clientNotificationToken)) {
            DefaultErrorResponse errorResponse = new DefaultErrorResponse();
            errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
            errorResponse.setType(INVALID_REQUEST);
            errorResponse.setReason("The client notification token is required if the Client is registered to use Ping or Push modes.");
            return errorResponse;
        }
    }
    if (Strings.isNotBlank(bindingMessage)) {
        final Pattern pattern = Pattern.compile(appConfiguration.getBackchannelBindingMessagePattern());
        if (!pattern.matcher(bindingMessage).matches()) {
            DefaultErrorResponse errorResponse = new DefaultErrorResponse();
            errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
            errorResponse.setType(INVALID_BINDING_MESSAGE);
            errorResponse.setReason("The provided binding message is unacceptable. It must match the pattern: " + pattern.pattern());
            return errorResponse;
        }
    }
    if (BooleanUtils.isTrue(backchannelUserCodeParameter)) {
        if (Strings.isBlank(userCodeParam)) {
            DefaultErrorResponse errorResponse = new DefaultErrorResponse();
            errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
            errorResponse.setType(INVALID_USER_CODE);
            errorResponse.setReason("The user code is required.");
            return errorResponse;
        } else if (Strings.isBlank(userCode)) {
            DefaultErrorResponse errorResponse = new DefaultErrorResponse();
            errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
            errorResponse.setType(INVALID_USER_CODE);
            errorResponse.setReason("The user code is not set.");
            return errorResponse;
        } else if (!userCode.equals(userCodeParam)) {
            DefaultErrorResponse errorResponse = new DefaultErrorResponse();
            errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
            errorResponse.setType(INVALID_USER_CODE);
            errorResponse.setReason("The user code is not valid.");
            return errorResponse;
        }
    }
    if (requestedExpirity != null && (requestedExpirity < 1 || requestedExpirity > appConfiguration.getCibaMaxExpirationTimeAllowedSec())) {
        DefaultErrorResponse errorResponse = new DefaultErrorResponse();
        errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
        errorResponse.setType(INVALID_REQUEST);
        errorResponse.setReason("Requested expirity is not allowed.");
        return errorResponse;
    }
    return null;
}
Also used : Pattern(java.util.regex.Pattern) DefaultErrorResponse(io.jans.as.model.error.DefaultErrorResponse)

Example 5 with DefaultErrorResponse

use of io.jans.as.model.error.DefaultErrorResponse in project jans by JanssenProject.

the class UmaWebException method createErrorUri.

public static URI createErrorUri(String redirectUri, ErrorResponseFactory factory, UmaErrorResponseType errorType, String state) {
    try {
        DefaultErrorResponse error = factory.getErrorResponse(errorType);
        if (redirectUri.contains("?")) {
            redirectUri += "&";
        } else {
            redirectUri += "?";
        }
        redirectUri += "error=" + error.getErrorCode();
        redirectUri += "&error_description=" + URLEncoder.encode(error.getErrorDescription(), "UTF-8");
        if (StringUtils.isNotBlank(error.getErrorUri())) {
            redirectUri += "&error_uri=" + URLEncoder.encode(error.getErrorUri(), "UTF-8");
        }
        if (StringUtils.isNotBlank(state)) {
            redirectUri += "&state=" + state;
        }
        return new URI(redirectUri);
    } catch (Exception e) {
        LOGGER.error("Failed to construct uri: " + redirectUri, e);
        throw factory.createWebApplicationException(INTERNAL_SERVER_ERROR, UmaErrorResponseType.SERVER_ERROR, "Failed to construct uri");
    }
}
Also used : DefaultErrorResponse(io.jans.as.model.error.DefaultErrorResponse) URI(java.net.URI) WebApplicationException(javax.ws.rs.WebApplicationException)

Aggregations

DefaultErrorResponse (io.jans.as.model.error.DefaultErrorResponse)5 User (io.jans.as.common.model.common.User)2 OAuth2AuditLog (io.jans.as.server.model.audit.OAuth2AuditLog)2 AuthorizationGrant (io.jans.as.server.model.common.AuthorizationGrant)2 HttpServletResponse (javax.servlet.http.HttpServletResponse)2 WebApplicationException (javax.ws.rs.WebApplicationException)2 Response (javax.ws.rs.core.Response)2 JwkClient (io.jans.as.client.JwkClient)1 Client (io.jans.as.common.model.registration.Client)1 ECDSAPublicKey (io.jans.as.model.crypto.signature.ECDSAPublicKey)1 RSAPublicKey (io.jans.as.model.crypto.signature.RSAPublicKey)1 SignatureAlgorithm (io.jans.as.model.crypto.signature.SignatureAlgorithm)1 InvalidClaimException (io.jans.as.model.exception.InvalidClaimException)1 InvalidJwtException (io.jans.as.model.exception.InvalidJwtException)1 ECDSASigner (io.jans.as.model.jws.ECDSASigner)1 RSASigner (io.jans.as.model.jws.RSASigner)1 Jwt (io.jans.as.model.jwt.Jwt)1 JwtAuthorizationRequest (io.jans.as.server.model.authorize.JwtAuthorizationRequest)1 CibaRequestCacheControl (io.jans.as.server.model.common.CibaRequestCacheControl)1 SessionClient (io.jans.as.server.model.session.SessionClient)1