Example #1
0
        public void PopulateProviderCredentials_MicrosoftAccount_CreatesExpectedCredentials()
        {
            const string UserIdClaimValue = "MicrosoftId";

            MicrosoftAccountCredentials credentials = new MicrosoftAccountCredentials();

            TokenResult tokenResult = new TokenResult();

            tokenResult.Properties.Add(TokenResult.Authentication.AccessTokenName, "TestAccessToken");
            tokenResult.Properties.Add(TokenResult.Authentication.RefreshTokenName, "TestRefreshToken");
            tokenResult.Properties.Add("AccessTokenExpiration", "2015-03-12T16:49:28.504Z");
            Dictionary <string, string> claims = new Dictionary <string, string>
            {
                { "Claim1", "Value1" },
                { "Claim2", "Value1" },
                { "Claim3", "Value1" },
                { ClaimTypes.NameIdentifier, UserIdClaimValue }
            };

            tokenResult.Claims = claims;

            MobileAppUser.PopulateProviderCredentials(tokenResult, credentials);

            Assert.Equal("TestAccessToken", credentials.AccessToken);
            Assert.Equal("TestRefreshToken", credentials.RefreshToken);
            Assert.Equal(DateTimeOffset.Parse("2015-03-12T16:49:28.504Z"), credentials.AccessTokenExpiration);
            Assert.Equal(UserIdClaimValue, credentials.UserId);
            Assert.Equal(claims.Count, credentials.Claims.Count);
        }
        public void TryParseLoginToken_NoTokenValidation_ReturnsExpectedClaims()
        {
            // Arrange
            Mock <MobileAppTokenHandler>       tokenHandlerMock = new Mock <MobileAppTokenHandler>(this.config);
            MobileAppAuthenticationHandlerMock authHandlerMock  = new MobileAppAuthenticationHandlerMock(this.loggerMock.Object, tokenHandlerMock.Object);
            MobileAppAuthenticationOptions     skipOptions      = new MobileAppAuthenticationOptions();

            skipOptions.SigningKey = "SOME_SIGNING_KEY";
            skipOptions.SkipTokenSignatureValidation = true;

            JwtSecurityToken skipToken = GetTestToken("SOME_OTHER_KEY");

            // Act
            ClaimsPrincipal skipClaimsPrincipal;
            bool            skipResult = authHandlerMock.TryParseLoginToken(skipToken.RawData, skipOptions, out skipClaimsPrincipal);

            // Assert
            tokenHandlerMock.Verify(h => h.TryValidateLoginToken(It.IsAny <string>(), It.IsAny <string>(), out skipClaimsPrincipal), Times.Never);
            Assert.True(skipResult);
            MobileAppUser user = this.tokenHandler.CreateServiceUser((ClaimsIdentity)skipClaimsPrincipal.Identity, skipToken.RawData);

            Assert.Equal("Facebook:1234", user.Id);
            Assert.True(user.Identity.IsAuthenticated);

            Claim[] claims = user.Claims.ToArray();
            Assert.Equal(8, claims.Length);
            Assert.Equal("Frank", claims.Single(p => p.Type == ClaimTypes.GivenName).Value);
            Assert.Equal("Miller", claims.Single(p => p.Type == ClaimTypes.Surname).Value);
            Assert.Equal("Admin", claims.Single(p => p.Type == ClaimTypes.Role).Value);
            Assert.Equal("Facebook:1234", claims.Single(p => p.Type == "uid").Value);
            Assert.Equal("MyClaimValue", claims.Single(p => p.Type == "my_custom_claim").Value);
        }
Example #3
0
        public async Task GetIdentitiesAsync_Throws_IfGatewayUrlNotInAppSettings()
        {
            // Arrange
            ConfigurationManager.AppSettings["EMA_RuntimeUrl"] = null;
            // ServiceUser should be authenticated to hit the exception
            MobileAppUser user = new MobileAppUser(CreateMockClaimsIdentity(Enumerable.Empty <Claim>(), true));

            user.MobileAppAuthenticationToken = "1234567890";
            NullReferenceException ex = null;

            // Act
            try
            {
                ex = await Assert.ThrowsAsync <NullReferenceException>(() => user.GetIdentityAsync <FacebookCredentials>());
            }
            finally
            {
                // reset the config for future tests
                ConfigurationManager.RefreshSection("appSettings");
            }

            // Assert
            Assert.NotNull(ex);
            Assert.Equal("The 'EMA_RuntimeUrl' app setting is missing from the configuration.", ex.Message);
        }
Example #4
0
        public void PopulateProviderCredentials_Facebook_CreatesExpectedCredentials()
        {
            const string UserIdClaimValue = "FacebookId";

            FacebookCredentials credentials = new FacebookCredentials();

            TokenResult tokenResult = new TokenResult();

            tokenResult.Properties.Add(TokenResult.Authentication.AccessTokenName, "TestAccessToken");
            Dictionary <string, string> claims = new Dictionary <string, string>
            {
                { "Claim1", "Value1" },
                { "Claim2", "Value1" },
                { "Claim3", "Value1" },
                { ClaimTypes.NameIdentifier, UserIdClaimValue }
            };

            tokenResult.Claims = claims;

            MobileAppUser.PopulateProviderCredentials(tokenResult, credentials);

            Assert.Equal("TestAccessToken", credentials.AccessToken);
            Assert.Equal(UserIdClaimValue, credentials.UserId);
            Assert.Equal(claims.Count, credentials.Claims.Count);
        }
        public void TryParseLoginToken_ReturnsExpectedClaims()
        {
            // Arrange
            MobileAppAuthenticationOptions options = new MobileAppAuthenticationOptions();

            options.SigningKey = "SOME_SIGNING_KEY";
            // SkipTokenSignatureValidation defaults to false
            JwtSecurityToken token = GetTestToken(options.SigningKey);

            // Act
            ClaimsPrincipal claimsPrincipal;
            bool            result = this.handlerMock.TryParseLoginToken(token.RawData, options, out claimsPrincipal);

            // Assert
            Assert.True(result);
            MobileAppUser user = this.tokenHandler.CreateServiceUser((ClaimsIdentity)claimsPrincipal.Identity, token.RawData);

            Assert.Equal("Facebook:1234", user.Id);
            Assert.True(user.Identity.IsAuthenticated);

            Claim[] claims = user.Claims.ToArray();
            Assert.Equal(8, claims.Length);
            Assert.Equal("Frank", claims.Single(p => p.Type == ClaimTypes.GivenName).Value);
            Assert.Equal("Miller", claims.Single(p => p.Type == ClaimTypes.Surname).Value);
            Assert.Equal("Admin", claims.Single(p => p.Type == ClaimTypes.Role).Value);
            Assert.Equal("Facebook:1234", claims.Single(p => p.Type == "uid").Value);
            Assert.Equal("MyClaimValue", claims.Single(p => p.Type == "my_custom_claim").Value);
        }
Example #6
0
        public void IsTokenValid_ReturnsTrue_WhenTokenIsValid()
        {
            // Arrange
            TokenResult tokenResult = new TokenResult();

            // Act
            bool result = MobileAppUser.IsTokenValid(tokenResult);

            // Assert
            Assert.True(result);
        }
Example #7
0
        public async Task GetIdentitiesAsync_ReturnsNull_IfUserNotAuthenticated()
        {
            // Arrange
            MobileAppUser user = new MobileAppUser(CreateMockClaimsIdentity(Enumerable.Empty <Claim>(), false));

            // Act
            var tokenResult = await user.GetIdentityAsync <FacebookCredentials>();

            // Assert
            Assert.Null(tokenResult);
        }
Example #8
0
        public void UserPropertiesAreValid()
        {
            // Arrange

            // Act
            MobileAppUser user = this.CreateTestUser();

            // Assert
            this.tokenHandlerMock.Verify();
            Assert.Equal(this.facebookCredentials.UserId, user.Id);
            Assert.True(user.Identity.IsAuthenticated);
        }
Example #9
0
        private void ValidateLoginToken(string token, FacebookCredentials expectedCredentials)
        {
            // validate the token and get the claims principal
            ClaimsPrincipal claimsPrincipal = null;

            Assert.True(this.tokenHandler.TryValidateLoginToken(token, TestSecretKey, out claimsPrincipal));

            // create a user from the token and validate properties
            MobileAppUser user = this.tokenHandler.CreateServiceUser((ClaimsIdentity)claimsPrincipal.Identity, token);

            Assert.Equal(expectedCredentials.UserId, user.Id);
            Assert.Equal(token, user.MobileAppAuthenticationToken);
        }
Example #10
0
        public async Task GetIdentitiesAsync_ReturnsNull_IfMobileAppAuthenticationTokenIsNullOrEmpty(string token)
        {
            // Arrange
            MobileAppUser user = new MobileAppUser(CreateMockClaimsIdentity(Enumerable.Empty <Claim>(), true));

            user.MobileAppAuthenticationToken = token;

            // Act
            var tokenResult = await user.GetIdentityAsync <FacebookCredentials>();

            // Assert
            Assert.Null(tokenResult);
        }
Example #11
0
        private IHttpActionResult GetUserDetails()
        {
            MobileAppUser user    = this.User as MobileAppUser;
            JObject       details = null;

            if (user != null)
            {
                details = new JObject
                {
                    { "id", user.Id },
                };
            }
            return(this.Json(details));
        }
Example #12
0
        public void IsTokenValid_ReturnsFalse_WhenTokenIsInvalid()
        {
            // Arrange
            // This is what is returned when a token is not found.
            TokenResult tokenResult = new TokenResult()
            {
                Diagnostics = "Token not found in store. id=sid:90BF712CA4464DDCADED130D8E5D1D8E, name=Twitter"
            };

            // Act
            bool result = MobileAppUser.IsTokenValid(tokenResult);

            // Assert
            Assert.False(result);
        }
Example #13
0
        public async Task <IActionResult> OnGetAsync(string id)
        {
            if (id == null)
            {
                return(NotFound());
            }

            MobileAppUser = await _context.MobileAppUsers.FirstOrDefaultAsync(m => m.Id == id);

            if (MobileAppUser == null)
            {
                return(NotFound());
            }
            return(Page());
        }
Example #14
0
        public void CreateUser_DoesNotSetUserId_WhenSpecifiedLevelIsNotUser()
        {
            // Arrange
            List <Claim> claims = new List <Claim>
            {
                new Claim(ClaimTypes.NameIdentifier, "provider:providerId"),
            };
            ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims);

            // Act
            MobileAppUser user = this.tokenHandler.CreateServiceUser(claimsIdentity, null);

            // Assert
            Assert.Null(user.Id);
            Assert.False(user.Identity.IsAuthenticated);
        }
Example #15
0
        public async Task <IActionResult> OnPostAsync(string id)
        {
            if (id == null)
            {
                return(NotFound());
            }

            MobileAppUser = await _context.MobileAppUsers.FindAsync(id);

            if (MobileAppUser != null)
            {
                _context.MobileAppUsers.Remove(MobileAppUser);
                await _context.SaveChangesAsync();
            }

            return(RedirectToPage("./Index"));
        }
Example #16
0
        /// <summary>
        /// Create a test user
        /// </summary>
        private MobileAppUser CreateTestUser()
        {
            Claim[] claims = new Claim[]
            {
                new Claim(ClaimTypes.NameIdentifier, this.facebookCredentials.UserId)
            };
            TokenInfo        info  = this.tokenHandler.CreateTokenInfo(claims, TimeSpan.FromDays(10), this.key);
            JwtSecurityToken token = info.Token;

            ClaimsPrincipal claimsPrincipal = null;

            this.tokenHandler.TryValidateLoginToken(token.RawData, this.key, out claimsPrincipal);

            MobileAppUser user = this.tokenHandler.CreateServiceUser((ClaimsIdentity)claimsPrincipal.Identity, null);

            return(user);
        }
Example #17
0
        public void CreateUser_ReturnsAnonymous_IfInvalidUserId(string invalidUserId)
        {
            // Arrange
            List <Claim> claims = new List <Claim>();

            if (invalidUserId != null)
            {
                claims.Add(new Claim(ClaimTypes.NameIdentifier, invalidUserId));
            }
            ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims);

            // Act
            MobileAppUser user = this.tokenHandler.CreateServiceUser(claimsIdentity, null);

            // Assert
            Assert.Null(user.Id);
            Assert.False(user.Identity.IsAuthenticated);
        }
Example #18
0
        public void CreateUser_ReturnsUser_IfUnknownProviderName()
        {
            // Arrange
            List <Claim> claims = new List <Claim>
            {
                new Claim(ClaimTypes.NameIdentifier, "unknown:providerId"),
            };

            // Fake that we've been authenticated
            Mock <ClaimsIdentity> mockClaimsIdentity = new Mock <ClaimsIdentity>(claims);

            mockClaimsIdentity.CallBase = true;
            mockClaimsIdentity.SetupGet(c => c.IsAuthenticated).Returns(true);

            // Act
            MobileAppUser user = this.tokenHandler.CreateServiceUser(mockClaimsIdentity.Object, null);

            // Assert
            Assert.Equal("unknown:providerId", user.Id);
            Assert.True(user.Identity.IsAuthenticated);
        }
Example #19
0
        public void PopulateProviderCredentials_Twitter_CreatesExpectedCredentials()
        {
            TwitterCredentials credentials = new TwitterCredentials();

            TokenResult tokenResult = new TokenResult();

            tokenResult.Properties.Add(TokenResult.Authentication.AccessTokenName, "TestAccessToken");
            tokenResult.Properties.Add("AccessTokenSecret", "TestAccessTokenSecret");
            Dictionary <string, string> claims = new Dictionary <string, string>
            {
                { "Claim1", "Value1" },
                { "Claim2", "Value1" },
                { "Claim3", "Value1" }
            };

            tokenResult.Claims = claims;

            MobileAppUser.PopulateProviderCredentials(tokenResult, credentials);

            Assert.Equal("TestAccessToken", credentials.AccessToken);
            Assert.Equal("TestAccessTokenSecret", credentials.AccessTokenSecret);
            Assert.Equal(claims.Count, credentials.Claims.Count);
        }
Example #20
0
        public void CreateUser_DeterminesUserIdFromClaims()
        {
            // single uid claim
            Claim[] claims = new Claim[]
            {
                new Claim("uid", "Facebook:1234")
            };
            ClaimsIdentity claimsIdentity = CreateMockClaimsIdentity(claims, true);
            MobileAppUser  user           = this.tokenHandler.CreateServiceUser(claimsIdentity, null);

            Assert.Equal("Facebook:1234", user.Id);

            // single NameIdentifier claim
            claims = new Claim[]
            {
                new Claim(ClaimTypes.NameIdentifier, "Facebook:1234")
            };
            claimsIdentity = CreateMockClaimsIdentity(claims, true);
            user           = this.tokenHandler.CreateServiceUser(claimsIdentity, null);
            Assert.Equal("Facebook:1234", user.Id);

            // BOTH uid and NameIdentifier claims
            // expect the NameIdentifier claim to take precedence
            claims = new Claim[]
            {
                new Claim("uid", "Facebook:1234"),
                new Claim(ClaimTypes.NameIdentifier, "Google:5678")
            };
            claimsIdentity = CreateMockClaimsIdentity(claims, true);
            user           = this.tokenHandler.CreateServiceUser(claimsIdentity, null);
            Assert.Equal("Google:5678", user.Id);

            // if there are no claims, the user id will be null
            claimsIdentity = CreateMockClaimsIdentity(Enumerable.Empty <Claim>(), true);
            user           = this.tokenHandler.CreateServiceUser(claimsIdentity, null);
            Assert.Equal(null, user.Id);
        }
        public string Get()
        {
            MobileAppUser user = this.User as MobileAppUser;

            return("Hello from secured controller! UserId: " + user.Id);
        }
        /// <inheritdoc />
        public virtual MobileAppUser CreateServiceUser(ClaimsIdentity claimsIdentity, string authToken)
        {
            MobileAppUser user = new MobileAppUser(claimsIdentity);

            if (user.Identity.IsAuthenticated)
            {
                // Determine the user ID based on either the uid or NameIdentifier claims.
                string userIdValue = claimsIdentity.GetClaimValueOrNull(ClaimTypes.NameIdentifier) ?? claimsIdentity.GetClaimValueOrNull("uid");
                string prefix;
                string userId;
                if (!string.IsNullOrEmpty(userIdValue) &&
                    this.TryParseUserId(userIdValue, out prefix, out userId))
                {
                    user.Id = userIdValue;
                    user.MobileAppAuthenticationToken = authToken;
                }
                else
                {
                    // if no user name specified or the format is invalid,
                    // set to anonymous
                    SetAnonymousUser(user);
                }
            }

            return user;
        }
        internal static MobileAppUser SetAnonymousUser(MobileAppUser user)
        {
            if (user != null)
            {
                user.Id = null;
                user.MobileAppAuthenticationToken = null;
            }

            return user;
        }
        public async Task GetIdentitiesAsync_Throws_IfGatewayUrlNotInAppSettings()
        {
            // Arrange
            ConfigurationManager.AppSettings["EMA_RuntimeUrl"] = null;
            // ServiceUser should be authenticated to hit the exception
            MobileAppUser user = new MobileAppUser(CreateMockClaimsIdentity(Enumerable.Empty<Claim>(), true));
            user.MobileAppAuthenticationToken = "1234567890";
            NullReferenceException ex = null;

            // Act
            try
            {
                ex = await Assert.ThrowsAsync<NullReferenceException>(() => user.GetIdentityAsync<FacebookCredentials>());
            }
            finally
            {
                // reset the config for future tests
                ConfigurationManager.RefreshSection("appSettings");
            }

            // Assert
            Assert.NotNull(ex);
            Assert.Equal("The 'EMA_RuntimeUrl' app setting is missing from the configuration.", ex.Message);
        }
        public async Task GetIdentitiesAsync_ReturnsNull_IfMobileAppAuthenticationTokenIsNullOrEmpty(string token)
        {
            // Arrange
            MobileAppUser user = new MobileAppUser(CreateMockClaimsIdentity(Enumerable.Empty<Claim>(), true));
            user.MobileAppAuthenticationToken = token;

            // Act
            var tokenResult = await user.GetIdentityAsync<FacebookCredentials>();

            // Assert
            Assert.Null(tokenResult);
        }
        public async Task GetIdentitiesAsync_ReturnsNull_IfUserNotAuthenticated()
        {
            // Arrange
            MobileAppUser user = new MobileAppUser(CreateMockClaimsIdentity(Enumerable.Empty<Claim>(), false));

            // Act
            var tokenResult = await user.GetIdentityAsync<FacebookCredentials>();

            // Assert
            Assert.Null(tokenResult);
        }
        /// <summary>
        /// Enables the registration of a device installation for push notifications via PUT request.
        /// If the specified installationId does not exist on the notification hub, a new installation is created and registered.
        /// If the specified installationId already exists, the installation is modified.
        /// </summary>
        /// <param name="installationId">The installation id to register or modify.</param>
        /// <param name="notificationInstallation">The <see cref="NotificationInstallation"/> object to register.</param>
        /// <returns><see cref="HttpResponseMessage"/> describing the result of the operation.</returns>
        public async Task <HttpResponseMessage> PutInstallation(string installationId, NotificationInstallation notificationInstallation)
        {
            if (!ModelState.IsValid)
            {
                throw new HttpResponseException(this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState));
            }

            this.ValidateInstallationId(installationId);
            this.ValidateNotificationInstallation(installationId, notificationInstallation);

            ITraceWriter traceWriter = this.Configuration.Services.GetTraceWriter();

            // The installation object that will be sent to NH.
            Installation     installation = this.CreateInstallation(notificationInstallation);
            HashSet <string> tagsAssociatedWithInstallationId = await this.GetTagsAssociatedWithInstallationId(notificationInstallation.InstallationId);

            MobileAppUser serviceUser = this.GetCurrentUser();

            if (tagsAssociatedWithInstallationId.Count == 0)
            {
                // Installation does not exist on NH.  Add it.
                if (installation.Tags == null)
                {
                    installation.Tags = new List <string>();
                }

                // Tag the installation with the UserId if authenticated.
                if (serviceUser != null && serviceUser.Identity.IsAuthenticated)
                {
                    string incomingUserTag = string.Format(UserIdTagPlaceholder, serviceUser.Id);
                    installation.Tags.Add(incomingUserTag);
                }

                try
                {
                    await this.UpsertInstallationAsync(installation);
                }
                catch (HttpResponseException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    string error = RResources.NotificationHub_CreateOrUpdateInstallationFailed.FormatForUser(installationId, ex.Message);

                    traceWriter.Error(error, ex, this.Request, ServiceLogCategories.NotificationControllers);
                    traceWriter.Error(error, ex, this.Request, LogCategories.NotificationControllers);

                    // We return 4xx status code on error as it is impossible to know whether it is bad input or a
                    // server error from NH. As a result we err on the bad request side.
                    return(this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex.Message));
                }
            }
            else
            {
                // Installation already existed on NH.
                if (serviceUser != null && serviceUser.Identity.IsAuthenticated)
                {
                    // Because the user is authenticated, copy all previous tags except UserId.
                    CopyTagsToInstallation(installation, tagsAssociatedWithInstallationId, false);

                    // Add the incoming UserId.
                    string incomingUserTag = string.Format(UserIdTagPlaceholder, serviceUser.Id);
                    AddTagToInstallation(installation, incomingUserTag);
                }
                else
                {
                    // Because the request is anonymous, copy all previous tags to the installation object, including the previous user tag.
                    CopyTagsToInstallation(installation, tagsAssociatedWithInstallationId, true);
                }

                try
                {
                    await this.UpsertInstallationAsync(installation);
                }
                catch (HttpResponseException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    string error = RResources.NotificationHub_CreateOrUpdateInstallationFailed.FormatForUser(installationId, ex.Message);

                    traceWriter.Error(error, ex, this.Request, ServiceLogCategories.NotificationControllers);
                    traceWriter.Error(error, ex, this.Request, LogCategories.NotificationControllers);

                    // We return 4xx status code on error as it is impossible to know whether it is bad input or a
                    // server error from NH. As a result we err on the bad request side.
                    return(this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex.Message));
                }
            }

            return(this.Request.CreateResponse(HttpStatusCode.OK));
        }