Exemple #1
0
        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            try
            {
                var token = context.Request.Raw["token"];

                var userId = await GetFacebookUserIdFromTokenAsync(context, token);

                if (userId == null)
                {
                    return;
                }
                _logger.LogDebug("FacebookSignIn: Signing in: {0}", userId);

                User user = await GetOrCreateUserAsync(userId);

                var claims = await _userClaimsProvider.GetUserClaimsAsync(user);

                context.Result = new GrantValidationResult(user.UserId, "nether-facebook", claims);

                _appMonitor.LogEvent("LoginSucceeded", properties: new Dictionary <string, string> {
                    { "LoginType", "fb-usertoken" }
                });
            }
            catch (Exception ex)
            {
                _logger.LogError("Error in ValidateAsync: {0}", ex);
                _appMonitor.LogError(ex, "Error in ValidateAsync", new Dictionary <string, string> {
                    { "EventType", "LoginFailed" },
                    { "EventSubType", "UnhandledException" },
                    { "LoginType", "fb-usertoken" }
                });
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, ex.Message);
            }
        }
Exemple #2
0
        public async Task <IActionResult> SetGamertagForPlayerId(
            [FromRoute] string playerid,
            [FromBody] SetGamertagRequestModel model)
        {
            var player = await _store.GetPlayerDetailsByUserIdAsync(playerid);

            if (player == null)
            {
                player = new Player {
                    UserId = playerid
                };
            }
            if (!string.IsNullOrEmpty(player.Gamertag))
            {
                _logger.LogInformation("Player already has gamertag (cannot update) in SetGamertagForPlayerId");
                _appMonitor.LogEvent("RegisterFailed", properties: new Dictionary <string, string> {
                    { "Reason", "UserAlreadyHasGamertag" },
                    { "Source", "Interactive" }
                });
                return(this.ValidationFailed(new ErrorDetail("gamertag", "Cannot update gamertag")));
            }

            player.Gamertag = model.Gamertag;
            await _store.SavePlayerAsync(player);

            _appMonitor.LogEvent("RegisterSucceeded", properties: new Dictionary <string, string> {
                { "Reason", "UserAlreadyHasGamertag" },
                { "Source", "Interactive" }
            });

            return(Ok());
        }
Exemple #3
0
        public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            var userName = context.UserName;
            var user     = await _userStore.GetUserByLoginAsync(LoginProvider.UserNamePassword, userName);

            if (user == null)
            {
                _logger.LogTrace("User not found: '{0}'", userName);
                _appMonitor.LogEvent("LoginFailed", "ResourceOwner: user not found", new Dictionary <string, string> {
                    { "EventSubType", "UserNotFound" },
                    { "LoginType", "password" }
                });
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest);
                return;
            }
            if (!user.IsActive)
            {
                _logger.LogTrace("User inactive: '{0}'", userName);
                _appMonitor.LogEvent("LoginFailed", "ResourceOwner: user inactive", new Dictionary <string, string> {
                    { "EventSubType", "UserInactive" },
                    { "LoginType", "password" }
                });
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest);
                return;
            }


            var login = user.Logins.FirstOrDefault(l => l.ProviderType == LoginProvider.UserNamePassword);

            if (login == null)
            {
                // shouldn't get here!
                _logger.LogError("User does not have a username password login entry: '{0}'", userName);
                _appMonitor.LogEvent("LoginFailed", "ResourceOwner: user has no password login entry", new Dictionary <string, string> {
                    { "EventSubType", "UserHasNoPassword" },
                    { "LoginType", "password" }
                });
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest);
            }


            bool valid = _passwordHasher.VerifyHashedPassword(
                hashedPassword: login.ProviderData,
                providedPassword: context.Password);

            if (!valid)
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest);
                return;
            }


            var claims = await _userClaimsProvider.GetUserClaimsAsync(user);

            context.Result = new GrantValidationResult(user.UserId, "password", claims);
            _appMonitor.LogEvent("LoginSucceeded", properties: new Dictionary <string, string> {
                { "LoginType", "password" }
            });
        }
        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            try
            {
                var token = context.Request.Raw["token"];

                var facebookTokenDebug = await _facebookGraphService.TokenDebugAsync(token);

                if (!facebookTokenDebug.IsValid)
                {
                    var message = (string)facebookTokenDebug.Error.Message;
                    _logger.LogError("FacebookSignIn: invalid token: {0}", message);
                    _appMonitor.LogEvent("LoginFailed", $"FacebookSignIn: invalid token: {message}", new Dictionary <string, string> {
                        { "EventSubType", "InvalidToken" },
                        { "LoginType", "fb-usertoken" }
                    });
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest);
                    return;
                }
                if (facebookTokenDebug.Error != null) // still got another error
                {
                    var message = (string)facebookTokenDebug.Error.Message;
                    _logger.LogError("FacebookSignIn: error validating token: {0}", message);
                    _appMonitor.LogEvent("LoginFailed", $"FacebookSignIn: error validating token: {message}", new Dictionary <string, string> {
                        { "EventSubType", "TokenValidationFailed" },
                        { "LoginType", "fb-usertoken" }
                    });
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest);
                    return;
                }

                var userId = facebookTokenDebug.UserId;
                if (userId == null)
                {
                    return;
                }
                _logger.LogDebug("FacebookSignIn: Signing in: {0}", userId);

                User user = await GetOrCreateUserAsync(userId);

                var claims = await _userClaimsProvider.GetUserClaimsAsync(user);

                context.Result = new GrantValidationResult(user.UserId, "nether-facebook", claims);

                _appMonitor.LogEvent("LoginSucceeded", properties: new Dictionary <string, string> {
                    { "LoginType", "fb-usertoken" }
                });
            }
            catch (Exception ex)
            {
                _logger.LogError("Error in ValidateAsync: {0}", ex);
                _appMonitor.LogError(ex, "Error in ValidateAsync", new Dictionary <string, string> {
                    { "EventType", "LoginFailed" },
                    { "EventSubType", "UnhandledException" },
                    { "LoginType", "fb-usertoken" }
                });
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, ex.Message);
            }
        }
        public async Task <IActionResult> Login(LoginInputModel model)
        {
            if (ModelState.IsValid)
            {
                // validate username/password against in-memory store
                var validationContext = new ResourceOwnerPasswordValidationContext {
                    UserName = model.Username, Password = model.Password
                };
                await _passwordValidator.ValidateAsync(validationContext);

                if (!validationContext.Result.IsError)
                {
                    AuthenticationProperties props = null;
                    // only set explicit expiration here if persistent.
                    // otherwise we reply upon expiration configured in cookie middleware.
                    if (AccountOptions.AllowRememberLogin && model.RememberLogin)
                    {
                        props = new AuthenticationProperties
                        {
                            IsPersistent = true,
                            ExpiresUtc   = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
                        };
                    }
                    ;

                    // issue authentication cookie with subject ID and username
                    var user = await _userStore.GetUserByLoginAsync(LoginProvider.UserNamePassword, model.Username);

                    var userId = user.UserId;
                    await HttpContext.Authentication.SignInAsync(userId, model.Username, props);

                    _appMonitor.LogEvent("LoginSucceeded", properties: new Dictionary <string, string> {
                        { "LoginType", "interactive" },
                        { "LoginSubType", "local" }
                    });

                    // make sure the returnUrl is still valid, and if yes - redirect back to authorize endpoint
                    if (_interaction.IsValidReturnUrl(model.ReturnUrl))
                    {
                        return(Redirect(model.ReturnUrl));
                    }

                    return(Redirect("~/"));
                }

                ModelState.AddModelError("", AccountOptions.InvalidCredentialsErrorMessage);
            }

            // something went wrong, show form with error
            var vm = await _account.BuildLoginViewModelAsync(model);

            return(View(vm));
        }
        public async Task <IActionResult> Get(string name)
        {
            var gamertag = User.GetGamerTag();

            _appMonitor.LogEvent("Leaderboard", properties: new Dictionary <string, string> {
                { "Name", name }
            });

            LeaderboardConfig config = _leaderboardProvider.GetByName(name);

            if (config == null)
            {
                return(NotFound());
            }
            LeaderboardType  type = config.Type;
            List <GameScore> scores;

            switch (type)
            {
            case LeaderboardType.AroundMe:
                if (gamertag == null)
                {
                    return(this.ValidationFailed(new ErrorDetail("gamertag", "Must be signed in as a player with a gamertag to retrive this leaderboard")));
                }
                scores = await _store.GetScoresAroundMeAsync(gamertag, config.Radius);

                break;

            case LeaderboardType.Top:
                scores = await _store.GetTopHighScoresAsync(config.Top);

                break;

            default:
                scores = await _store.GetAllHighScoresAsync();

                break;
            }

            GameScore currentPlayer = null;

            if (config.IncludeCurrentPlayer && gamertag != null)
            {
                currentPlayer = (await _store.GetScoresAroundMeAsync(gamertag, 0)).FirstOrDefault();
            }

            // Format response model
            var resultModel = new LeaderboardGetResponseModel
            {
                Entries = scores
                          ?.Select(s => LeaderboardGetResponseModel.LeaderboardEntry.Map(s, gamertag))
                          ?.ToList(),
                CurrentPlayer = LeaderboardGetResponseModel.LeaderboardEntry.Map(currentPlayer, null)
            };

            // Return result
            return(Ok(resultModel));
        }
Exemple #7
0
        public async Task <IActionResult> Post([FromBody] ScorePostRequestModel request)
        {
            //TODO: Make validation more sophisticated, perhaps some games want/need negative scores
            // Validate input
            if (request.Score < 0)
            {
                _logger.LogError("score is negative ({0})", request.Score);
                _appMonitor.LogEvent("InvalidScore", properties: new Dictionary <string, string> {
                    { "Score", request.Score.ToString() }
                });
                return(this.ValidationFailed(new ErrorDetail("score", "Score cannot be negative")));
            }

            //TODO: Handle exceptions and retries
            var gamertag = User.GetGamerTag();

            if (string.IsNullOrWhiteSpace(gamertag))
            {
                _logger.LogError("User has no gamertag: '{0}'", User.GetId());
                return(this.ValidationFailed(new ErrorDetail("gamertag", "The user doesn't have a gamertag")));
            }


            var userId = User.GetId();

            // Save score and call analytics in parallel
            await Task.WhenAll(
                _store.SaveScoreAsync(new GameScore
            {
                UserId  = userId,
                Country = request.Country,
                Score   = request.Score
            }),
                SendScoreEventAndLogErrors(request));

            _appMonitor.LogEvent("Score", properties: new Dictionary <string, string> {
                { "Score", request.Score.ToString() }
            });

            // Return result
            return(Ok());
        }
Exemple #8
0
        public async Task <IActionResult> PutCurrentPlayer([FromBody] PlayerPutRequestModel player)
        {
            string userId = User.GetId();

            bool newPlayer    = false;
            var  playerEntity = await _store.GetPlayerDetailsByUserIdAsync(userId);

            if (playerEntity == null)
            {
                newPlayer = true;
                if (player.Gamertag != null)
                {
                    // check if gamertag is already in use
                    var existingPlayerForGamertag = await _store.GetPlayerDetailsByUserIdAsync(player.Gamertag);

                    if (existingPlayerForGamertag != null && existingPlayerForGamertag.UserId != userId)
                    {
                        // Can't use a gamertag from another user
                        return(this.ValidationFailed(new ErrorDetail("gamertag", "Gamertag already in use")));
                    }
                }
                playerEntity = new Player
                {
                    UserId    = userId,
                    Gamertag  = player.Gamertag,
                    Country   = player.Country,
                    CustomTag = player.CustomTag
                };
            }
            else
            {
                if (playerEntity.Gamertag != player.Gamertag)
                {
                    // can't change gamertag
                    return(this.ValidationFailed(new ErrorDetail("gamertag", "Can't change gamertag")));
                }
                playerEntity.Country   = player.Country;
                playerEntity.CustomTag = player.CustomTag;
            }
            // Update player
            await _store.SavePlayerAsync(playerEntity);

            // is this a new player registration?
            if (newPlayer)
            {
                _appMonitor.LogEvent("Register");
            }

            // Return result
            return(NoContent());
        }
Exemple #9
0
        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            var guestIdentifier = context.Request.Raw["guest_identifier"];

            _logger.LogInformation("GuestAccessToken: Signing in with guest access token '{0}'", guestIdentifier);

            User user = await GetOrCreateGuestUserAsync(guestIdentifier);

            var claims = await _userClaimsProvider.GetUserClaimsAsync(user);

            context.Result = new GrantValidationResult(user.UserId, "nether-guest", claims);

            _appMonitor.LogEvent("LoginSucceeded", properties: new Dictionary <string, string> {
                { "LoginType", "guest-access" }
            });
        }
        public async Task <IActionResult> Get(string name)
        {
            var userId = User.GetId();

            _appMonitor.LogEvent("Leaderboard", properties: new Dictionary <string, string> {
                { "Name", name }
            });

            LeaderboardConfig config = _leaderboardProvider.GetByName(name);

            if (config == null)
            {
                return(NotFound());
            }
            LeaderboardType  type = config.Type;
            List <GameScore> scores;

            switch (type)
            {
            case LeaderboardType.AroundMe:
                if (userId == null)
                {
                    return(this.ValidationFailed(new ErrorDetail("userId", "Must be signed in as a player with a userId to retrive this leaderboard")));
                }
                scores = await _store.GetScoresAroundUserAsync(userId, config.Radius);

                break;

            case LeaderboardType.Top:
                scores = await _store.GetTopHighScoresAsync(config.Top);

                break;

            default:
                scores = await _store.GetAllHighScoresAsync();

                break;
            }
            var userIdsToLookUp = scores.Select(s => s.UserId).ToList();

            GameScore currentPlayer = null;

            if (config.IncludeCurrentPlayer && userId != null)
            {
                currentPlayer = (await _store.GetScoresAroundUserAsync(userId, 0)).FirstOrDefault();
                if (currentPlayer != null && !userIdsToLookUp.Contains(currentPlayer.UserId))
                {
                    userIdsToLookUp.Add(currentPlayer.UserId);
                }
            }

            var gamertags = await _playerManagementClient.GetGamertagsForUserIdsAsync(userIdsToLookUp.ToArray());

            var resultModel = new LeaderboardGetResponseModel
            {
                Entries = scores
                          ?.Select(s => Map(s, userId))
                          ?.ToList(),
                CurrentPlayer = Map(currentPlayer, null)
            };

            return(Ok(resultModel));

            // local function to map to response types
            LeaderboardGetResponseModel.LeaderboardEntry Map(GameScore score, string currentUserId)
            {
                if (score == null)
                {
                    return(null);
                }

                //find gamertag for userid

                return(new LeaderboardGetResponseModel.LeaderboardEntry
                {
                    Gamertag = gamertags.Single(g => g.UserId == score.UserId).Gamertag,
                    Score = score.Score,
                    Rank = score.Rank,
                    IsCurrentPlayer = currentUserId == score.UserId
                });
            }
        }