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); }
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; } }
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()); }); } } }