public void JwtController_Refresh_HandlesBadInput() { /////////////////////////////////////////////////////////////////// // Arrange // // Options string secret = "A_KEY_MUST_BE_16_CHARS+"; SymmetricSecurityKey signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret.PadRight(16))); SigningCredentials signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); var jwtIssuerOptions = new JwtIssuerOptions { Issuer = "TokenIssuer", Audience = "TokenAudience", AccessValidFor = TimeSpan.FromSeconds(10), RefreshValidFor = TimeSpan.FromSeconds(100), AccessClockSkew = 0, RefreshClockSkew = 0, Subject = "Alice", SigningCredentials = signingCredentials }; var mockOptions = new Mock <IOptions <JwtIssuerOptions> >(); mockOptions.Setup(mo => mo.Value).Returns(jwtIssuerOptions); // UserManager var fakeUserManager = new FakeUserManager(); // TokenStore var tokenStore = new ExampleTokenStore(); // Configuration var mockConfiguration = new Mock <IConfiguration>(); mockConfiguration.SetupGet(m => m[Constants.SECRET_ENV_VAR]).Returns(secret); // Logger var mockLogger = new Mock <ILogger <JwtController> >(); JwtController controller = new JwtController(mockOptions.Object, fakeUserManager, tokenStore, mockConfiguration.Object, mockLogger.Object); // Act & Assert var actionResult = controller.Refresh(null); Assert.Equal("Microsoft.AspNetCore.Mvc.BadRequestObjectResult", actionResult.Result.GetType().ToString()); actionResult = controller.Refresh("TotalGarbage"); Assert.Equal("Microsoft.AspNetCore.Mvc.BadRequestObjectResult", actionResult.Result.GetType().ToString()); actionResult = controller.Refresh(""); Assert.Equal("Microsoft.AspNetCore.Mvc.BadRequestObjectResult", actionResult.Result.GetType().ToString()); }
public void JwtController_CanIssueAndRefreshTokens() { /////////////////////////////////////////////////////////////////// // Arrange // // Options string secret = "A_KEY_MUST_BE_16_CHARS+"; SymmetricSecurityKey signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret.PadRight(16))); SigningCredentials signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); var jwtIssuerOptions = new JwtIssuerOptions { Issuer = "TokenIssuer", Audience = "TokenAudience", AccessValidFor = TimeSpan.FromSeconds(10), RefreshValidFor = TimeSpan.FromSeconds(100), AccessClockSkew = 0, RefreshClockSkew = 0, Subject = "Alice", SigningCredentials = signingCredentials }; var mockOptions = new Mock <IOptions <JwtIssuerOptions> >(); mockOptions.Setup(mo => mo.Value).Returns(jwtIssuerOptions); // UserManager var fakeUserManager = new FakeUserManager(); // TokenStore var tokenStore = new ExampleTokenStore(); // Configuration var mockConfiguration = new Mock <IConfiguration>(); mockConfiguration.SetupGet(m => m[Constants.SECRET_ENV_VAR]).Returns(secret); // Logger var mockLogger = new Mock <ILogger <JwtController> >(); JwtController controller = new JwtController(mockOptions.Object, fakeUserManager, tokenStore, mockConfiguration.Object, mockLogger.Object); // Credentials LoginCredentials creds = new LoginCredentials { UserName = "******", Password = "******" }; /////////////////////////////////////////////////////////////////// // Act // var issueResult = controller.Issue(creds); var typedActionIssueResult = issueResult.Result as Microsoft.AspNetCore.Mvc.OkObjectResult; Assert.NotNull(typedActionIssueResult); string issueBody = typedActionIssueResult.Value as string; Assert.NotNull(issueBody); dynamic objResponses = null; bool bDeserialized = true; try { objResponses = JsonConvert.DeserializeObject <List <dynamic> >(issueBody); } catch { bDeserialized = false; } Assert.True(bDeserialized); if (!bDeserialized) { return; } // objResponses should be a list of dynamic objects, the first of // which should be an access token, the second of which should be // a refresh token var objResponse0 = objResponses[0]; // Access token wrapper var objResponse1 = objResponses[1]; // Refresh token wrapper string sRefreshToken = AppUtility.GetDynamicPropertyValueAsString(objResponse1, "refresh_token"); // Call the Refresh endpoint with the token to see if a new pair of tokens are issued. var refreshResult = controller.Refresh(sRefreshToken); checkActionResult(refreshResult.Result, jwtIssuerOptions, signingKey); }
public void JwtController_RefreshTokenClockSkewWorks() { /////////////////////////////////////////////////////////////////// // Arrange // // Options string secret = "A_KEY_MUST_BE_16_CHARS+"; SymmetricSecurityKey signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret.PadRight(16))); SigningCredentials signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); ///////////////////////// int iAccessValidFor = 3; int iRefreshValidFor = 6; // <- Short refresh time for testing UInt32 iRefreshClockSkew = 5; ///////////////////////// var jwtIssuerOptions = new JwtIssuerOptions { Issuer = "TokenIssuer", Audience = "TokenAudience", AccessValidFor = TimeSpan.FromSeconds(iAccessValidFor), RefreshValidFor = TimeSpan.FromSeconds(iRefreshValidFor), AccessClockSkew = 0, RefreshClockSkew = iRefreshClockSkew, Subject = "Alice", SigningCredentials = signingCredentials }; var mockOptions = new Mock <IOptions <JwtIssuerOptions> >(); mockOptions.Setup(mo => mo.Value).Returns(jwtIssuerOptions); // UserManager var fakeUserManager = new FakeUserManager(); // TokenStore var tokenStore = new ExampleTokenStore(); // Configuration var mockConfiguration = new Mock <IConfiguration>(); mockConfiguration.SetupGet(m => m[Constants.SECRET_ENV_VAR]).Returns(secret); // Logger var mockLogger = new Mock <ILogger <JwtController> >(); JwtController controller = new JwtController(mockOptions.Object, fakeUserManager, tokenStore, mockConfiguration.Object, mockLogger.Object); // Credentials LoginCredentials creds = new LoginCredentials { UserName = "******", Password = "******" }; /////////////////////////////////////////////////////////////////// // Act // var issueResult = controller.Issue(creds); var typedActionIssueResult = issueResult.Result as Microsoft.AspNetCore.Mvc.OkObjectResult; Assert.NotNull(typedActionIssueResult); string issueBody = typedActionIssueResult.Value as string; Assert.NotNull(issueBody); dynamic objResponses = null; bool bDeserialized = true; try { objResponses = JsonConvert.DeserializeObject <List <dynamic> >(issueBody); } catch { bDeserialized = false; } Assert.True(bDeserialized); if (!bDeserialized) { return; } // objResponses should be a list of dynamic objects, the first of // which should be an access token, the second of which should be // a refresh token var objResponse0 = objResponses[0]; // Access token wrapper var objResponse1 = objResponses[1]; // Refresh token wrapper string sRefreshToken = AppUtility.GetDynamicPropertyValueAsString(objResponse1, "refresh_token"); // ALLOW TIME TO ELAPSE SO THAT THE REFRESH TOKEN IS STALE IF // ZERO CLOCK SKEW, BUT JUST ABOUT ACCEPTABLE IF CLOCK SKEW IS WORKING System.Threading.Thread.Sleep(1000 * (iRefreshValidFor + (int)iRefreshClockSkew - 2)); // Sleep for at least the timeout time of the refresh token, plus 1 second // Call the Refresh endpoint with the token to see if a new pair of tokens are issued. var refreshResult = controller.Refresh(sRefreshToken); /////////////////////////////////////////////////////////////////// // Assert // var actionResult = refreshResult.Result; Assert.Equal("Microsoft.AspNetCore.Mvc.OkObjectResult", actionResult.GetType().ToString()); }
public void JwtController_CanIssueTokens() { /////////////////////////////////////////////////////////////////// // Arrange // // Options string secret = "A_KEY_MUST_BE_16_CHARS+"; SymmetricSecurityKey signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret.PadRight(16))); SigningCredentials signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); var jwtIssuerOptions = new JwtIssuerOptions { Issuer = "TokenIssuer", Audience = "TokenAudience", AccessValidFor = TimeSpan.FromSeconds(10), RefreshValidFor = TimeSpan.FromSeconds(100), AccessClockSkew = 0, RefreshClockSkew = 0, Subject = "Alice", SigningCredentials = signingCredentials }; var mockOptions = new Mock <IOptions <JwtIssuerOptions> >(); mockOptions.Setup(mo => mo.Value).Returns(jwtIssuerOptions); // UserManager var fakeUserManager = new FakeUserManager(); // TokenStore var tokenStore = new ExampleTokenStore(); // Configuration var mockConfiguration = new Mock <IConfiguration>(); mockConfiguration.SetupGet(m => m[Constants.SECRET_ENV_VAR]).Returns(secret); // Logger var mockLogger = new Mock <ILogger <JwtController> >(); JwtController controller = new JwtController(mockOptions.Object, fakeUserManager, tokenStore, mockConfiguration.Object, mockLogger.Object); // Credentials LoginCredentials creds = new LoginCredentials { UserName = "******", Password = "******" }; /////////////////////////////////////////////////////////////////// // Act // var result = controller.Issue(creds); /////////////////////////////////////////////////////////////////// // Assert // // Task should finish var resultStatus = result.Status; // Result should be 200 OK var actionResult = result.Result; checkActionResult(actionResult, jwtIssuerOptions, signingKey); }