private void OnGetApplicationAccount(ApplicationAccount account, AuthenticateRequest request, SendParameters sendParameters, NetworkProtocolType endpointProtocol)
        {
            if (!this.Connected)
            {
                if (log.IsDebugEnabled)
                {
                    log.DebugFormat("OnGetApplicationAccount: Client disconnected. Ignore response.");
                }
                return;
            }

            if (!ConnectionRequirementsChecker.Check(this, account.RequireSecureConnection, account.ApplicationId, this.authOnceUsed))
            {
                log.Warn(secureConnectionLogGuard,
                         $"Client used non secure connection type when it is required. appId:{account.ApplicationId}, Connection: {this.NetworkProtocol}. AuthOnce {this.authOnceUsed}");

                return;
            }


            if (log.IsDebugEnabled)
            {
                log.DebugFormat("OnGetApplicationAccount app:{0}, result:{1}, msg:{2}", account.ApplicationId,
                                account.AccountServiceResult, account.DebugMessage);
            }

            var operationRequest = request.OperationRequest;

            if (!account.IsAuthenticated)
            {
                if (log.IsInfoEnabled)
                {
                    log.InfoFormat("Authentication of client failed: Msg={0}, AppId={1}", account.DebugMessage, request.ApplicationId);
                }

                this.SendOperationResponse(new OperationResponse(operationRequest.OperationCode)
                {
                    ReturnCode   = (short)ErrorCode.InvalidAuthentication,
                    DebugMessage =
                        string.IsNullOrEmpty(account.DebugMessage) ? ErrorMessages.InvalidAppId : account.DebugMessage
                }, sendParameters);

                this.ScheduleDisconnect(this.GetDisconnectTime());
                return;
            }

            if (log.IsDebugEnabled)
            {
                log.DebugFormat(
                    "HandleAuthenticateRequest for App ID {0}, Private Cloud {1}, Service Type {2}, Region {3}",
                    request.ApplicationId,
                    account.PrivateCloud,
                    account.ServiceType,
                    request.Region);
            }

            // store for debugging purposes.
            this.authenticatedApplicationId = request.ApplicationId;

            // try to get the master server instance for the specified application id
            CloudPhotonEndpointInfo masterServer;
            string message;

            if (!((PhotonCloudApp)this.application).CloudCache.TryGetPhotonEndpoint(request, account, out masterServer, out message))
            {
                if (string.Equals(request.Region, "none", StringComparison.CurrentCultureIgnoreCase))
                {
                    if (log.IsDebugEnabled)
                    {
                        log.DebugFormat("MasterServer not found for region '{0}' on cloud '{1}' / service type '{2}': '{3}'. AppId: {4}/{5}",
                                        request.Region, account.PrivateCloud, account.ServiceType, message,
                                        request.ApplicationId, request.ApplicationVersion);
                    }
                }
                else
                {
                    if (log.IsWarnEnabled)
                    {
                        log.WarnFormat(masterNotFoundGuard, "MasterServer not found for region '{0}' on cloud '{1}' / service type '{2}': '{3}'. AppId: {4}/{5}",
                                       request.Region, account.PrivateCloud, account.ServiceType, message,
                                       request.ApplicationId, request.ApplicationVersion);
                    }
                }
                this.SendOperationResponse(new OperationResponse(operationRequest.OperationCode)
                {
                    ReturnCode   = (short)ErrorCode.InvalidRegion,
                    DebugMessage = string.Format("Cloud {0} / Region {1} is not available.", account.PrivateCloud, request.Region)
                }, sendParameters);

                this.ScheduleDisconnect(this.GetDisconnectTime());
                return;
            }

            var masterEndPoint = masterServer.GetEndPoint(endpointProtocol, this.LocalPort,
                                                          isIPv6: this.LocalIPAddressIsIPv6, useHostnames: this.IsIPv6ToIPv4Bridged);

            if (masterEndPoint == null)
            {
                if (log.IsWarnEnabled)
                {
                    log.WarnFormat(masterNotFoundForProtocolGuard,
                                   "Master server endpoint for protocol {0} not found on master server {1}. appId:{2}",
                                   this.NetworkProtocol, masterServer, account.ApplicationId);
                }

                this.SendOperationResponse(new OperationResponse(operationRequest.OperationCode)
                {
                    ReturnCode   = (short)AuthErrorCode.ProtocolNotSupported,
                    DebugMessage = ErrorMessages.ProtocolNotSupported
                }, sendParameters);

                this.ScheduleDisconnect(this.GetDisconnectTime());
                return;
            }

            // check for custom authentication
            if (account.IsClientAuthenticationEnabled)
            {
                var customAuthHandler = this.GetCustomAuthHandler(account);
                customAuthHandler.AuthenticateClient(this, request, account, sendParameters, account);

                return; // custom authentication is handled async
            }

            var response = this.HandleDefaultAuthenticateRequest(request, account, masterEndPoint, masterServer);

            this.SendOperationResponse(response, sendParameters);
            this.ScheduleDisconnect(this.MaxDisconnectTime);
        }
Example #2
0
        protected MasterClientPeer(InitRequest initRequest, bool derived)
            : base(initRequest)
        {
            this.SetCurrentOperationHandler(OperationHandlerInitial.Instance);

            this.ExpectedProtocol = initRequest.NetworkProtocol;

            this.RequestFiber.Enqueue(() =>
            {
                if (MasterApplication.AppStats != null)
                {
                    MasterApplication.AppStats.IncrementMasterPeerCount();
                    MasterApplication.AppStats.AddSubscriber(this);
                }
            }
                                      );

            this.HttpRpcCallsLimit = CommonSettings.Default.WebRpcHttpCallsLimit;

            AuthenticationToken authToken;

            if (initRequest.InitObject is string token)
            {
                ErrorCode errorCode;
                string    errorMsg;
                authToken = AuthOnInitHandler.DoAuthUsingInitObject(token, this, initRequest, ((MasterApplication)MasterApplication.Instance).TokenCreator,
                                                                    out errorCode, out errorMsg);

                if (authToken == null)
                {
                    this.RequestFiber.Enqueue(
                        () => this.SendOperationResponseAndDisconnect(new OperationResponse((byte)OperationCode.AuthOnce)
                    {
                        DebugMessage = errorMsg,
                        ReturnCode   = (short)errorCode
                    }, new SendParameters()));
                    return;
                }
            }
            else if (initRequest.DecryptedAuthToken != null)
            {
                authToken            = (AuthenticationToken)initRequest.DecryptedAuthToken;
                this.binaryTokenUsed = true;
            }
            else
            {
                this.StartWaitForAuthRequest();
                return;
            }

            if (authToken != null)
            {
                if (!derived && !ConnectionRequirementsChecker.Check(this, authToken.ApplicationId, authToken, true))
                {
                    log.Warn(secureConnectionLogGuard,
                             $"Client used non secure connection type when it is required. appId:{authToken.ApplicationId}, Connection: {this.NetworkProtocol}. AuthOnce");

                    return;
                }

                var app = (MasterApplication)ApplicationBase.Instance;
                if (app.DefaultApplication.IsActorExcluded(authToken.UserId))
                {
                    if (log.IsDebugEnabled)
                    {
                        log.DebugFormat("MasterClientPeer, actor '{0}' is excluded", authToken.UserId);
                    }

                    this.RequestFiber.Enqueue(
                        () => this.SendOperationResponseAndDisconnect(new OperationResponse((byte)OperationCode.AuthOnce)
                    {
                        DebugMessage = "User blocked",
                        ReturnCode   = (short)ErrorCode.UserBlocked,
                    }, new SendParameters()));
                    return;
                }

                this.authOnceUsed         = true;
                this.unencryptedAuthToken = authToken;

                this.UserId = authToken.UserId;
            }
        }
Example #3
0
        public OperationResponse HandleAuthenticate(OperationRequest operationRequest, SendParameters sendParameters)
        {
            // validate operation request
            var authenticateRequest = new AuthenticateRequest(this.Protocol, operationRequest);

            if (authenticateRequest.IsValid == false)
            {
                return(OperationHandlerBase.HandleInvalidOperation(authenticateRequest, log));
            }

            this.StopWaitForAuthRequest();

            if (log.IsDebugEnabled)
            {
                log.DebugFormat(
                    "HandleAuthenticateRequest:appId={0};version={1};region={2};type={3};userId={4}",
                    authenticateRequest.ApplicationId,
                    authenticateRequest.ApplicationVersion,
                    authenticateRequest.Region,
                    authenticateRequest.ClientAuthenticationType,
                    authenticateRequest.UserId);
            }

            var app = (MasterApplication)ApplicationBase.Instance;

            if (authenticateRequest.IsTokenAuthUsed)
            {
                OperationResponse response;

                var authToken = GetValidAuthToken(authenticateRequest, out response);
                if (response != null || authToken == null)
                {
                    return(response);
                }

                if (app.DefaultApplication.IsActorExcluded(authToken.UserId))
                {
                    if (log.IsDebugEnabled)
                    {
                        log.DebugFormat("HandleAuthenticate, userId '{0}' is excluded", authToken.UserId);
                    }

                    response = new OperationResponse((byte)OperationCode.Authenticate)
                    {
                        DebugMessage = "User blocked",
                        ReturnCode   = (short)ErrorCode.UserBlocked
                    };
                    return(response);
                }

                this.UserId = authToken.UserId;
                this.unencryptedAuthToken = authToken;

                if (!ConnectionRequirementsChecker.Check(this, authenticateRequest.ApplicationId,
                                                         this.unencryptedAuthToken, this.authOnceUsed))
                {
                    log.Warn(secureConnectionLogGuard,
                             $"Client used non secure connection type when it is required. appId:{authenticateRequest.ApplicationId}, Connection: {this.NetworkProtocol}, Reqular Authentication");

                    return(null);
                }
                // publish operation response
                response = new OperationResponse(
                    authenticateRequest.OperationRequest.OperationCode,
                    new AuthenticateResponse
                {
                    QueuePosition = 0
                }
                    );
                response.Parameters.Add((byte)ParameterCode.Token, this.GetEncryptedAuthenticationToken(authenticateRequest));

                if (!string.IsNullOrEmpty(this.UserId))
                {
                    response.Parameters.Add((byte)ParameterCode.UserId, this.UserId);
                }

                if (log.IsDebugEnabled)
                {
                    log.DebugFormat("HandleAuthenticateRequest - Token Authentication done. Result: {0}; msg={1}", response.ReturnCode, response.DebugMessage);
                }

                this.SetCurrentOperationHandler(OperationHandlerDefault.Instance);

                this.Application = app.DefaultApplication;

                // check if the peer wants to receive lobby statistic events
                if (authenticateRequest.ReceiveLobbyStatistics)
                {
                    this.Application.LobbyStatsPublisher.Subscribe(this);
                }

                return(response);
            }


            // if authentication data is used it must be either a byte array or a string value
            if (authenticateRequest.ClientAuthenticationData != null)
            {
                var dataType = authenticateRequest.ClientAuthenticationData.GetType();
                if (dataType != typeof(byte[]) && dataType != typeof(string))
                {
                    if (log.IsDebugEnabled)
                    {
                        log.DebugFormat("HandleAuthenticateRequest - invalid type for auth data (datatype = {0}), request: {1}", dataType, operationRequest.ToString());
                    }

                    return(new OperationResponse
                    {
                        OperationCode = operationRequest.OperationCode,
                        ReturnCode = (short)ErrorCode.OperationInvalid,
                        DebugMessage = ErrorMessages.InvalidTypeForAuthData
                    });
                }
            }

            // check if custom client authentication is required
            if (app.CustomAuthHandler.IsClientAuthenticationEnabled)
            {
                if (app.TokenCreator == null)
                {
                    log.WarnFormat("No custom authentication supported: AuthTokenKey not specified in config.");

                    var response = new OperationResponse(authenticateRequest.OperationRequest.OperationCode)
                    {
                        ReturnCode   = (short)ErrorCode.InvalidAuthentication,
                        DebugMessage = ErrorMessages.AuthTokenTypeNotSupported
                    };

                    return(response);
                }


                this.SetCurrentOperationHandler(OperationHandlerAuthenticating.Instance);

                var authSettings = new AuthSettings
                {
                    IsAnonymousAccessAllowed = app.CustomAuthHandler.IsAnonymousAccessAllowed,
                };

                app.CustomAuthHandler.AuthenticateClient(this, authenticateRequest, authSettings, new SendParameters(), authSettings);
                return(null);
            }

            var authResponse = new OperationResponse(operationRequest.OperationCode)
            {
                Parameters = new Dictionary <byte, object>()
            };

            // TBD: centralizing setting of userid
            if (string.IsNullOrWhiteSpace(authenticateRequest.UserId))
            {
                this.UserId = Guid.NewGuid().ToString();
                authResponse.Parameters.Add((byte)ParameterCode.UserId, this.UserId);
            }
            else
            {
                this.UserId = authenticateRequest.UserId;
            }

            authResponse.Parameters.Add((byte)ParameterCode.Token, this.GetEncryptedAuthenticationToken(authenticateRequest));

            // apply application to the peer
            this.SetCurrentOperationHandler(OperationHandlerDefault.Instance);

            this.OnAuthSuccess(authenticateRequest);

            // publish operation response
            return(authResponse);
        }
        protected GameClientPeer(InitRequest initRequest, GameApplication application, bool derived)
            : base(initRequest)
        {
            this.application = application;

            if (this.application.AppStatsPublisher != null)
            {
                this.application.AppStatsPublisher.IncrementPeerCount();
            }

            this.HttpRpcCallsLimit = CommonSettings.Default.WebRpcHttpCallsLimit;

            var token = initRequest.InitObject as string;
            AuthenticationToken authToken = null;

            if (!string.IsNullOrEmpty(token))
            {
                ErrorCode errorCode;
                string    errorMsg;
                authToken = AuthOnInitHandler.DoAuthUsingInitObject(token, this, initRequest,
                                                                    application.TokenCreator, out errorCode, out errorMsg);
                if (authToken == null)
                {
                    this.RequestFiber.Enqueue(() => this.SendOperationResponse(new OperationResponse((byte)OperationCode.AuthOnce)
                    {
                        DebugMessage = errorMsg,
                        ReturnCode   = (short)errorCode
                    }, new SendParameters()));
                    this.ScheduleDisconnect();
                }
            }
            else if (initRequest.DecryptedAuthToken != null)
            {
                authToken            = (AuthenticationToken)initRequest.DecryptedAuthToken;
                this.binaryTokenUsed = true;
            }

            if (authToken != null)
            {
                this.authOnceUsed = true;
                this.AuthToken    = authToken;

                if (!derived)
                {
                    if (!ConnectionRequirementsChecker.Check(this, authToken.ApplicationId, authToken, this.authOnceUsed))
                    {
                        log.Warn(secureConnectionLogGuard,
                                 $"Client used non secure connection type when it is required. appId:{authToken.ApplicationId}, Connection: {this.NetworkProtocol}. AuthOnce");

                        return;
                    }

                    this.SetupPeer(this.AuthToken);

                    this.RequestFiber.Enqueue(() =>
                    {
                        var responseObject = new AuthenticateResponse {
                            QueuePosition = 0
                        };
                        this.SendOperationResponse(new OperationResponse((byte)OperationCode.AuthOnce, responseObject),
                                                   new SendParameters());
                    });
                }
            }
        }