private static TestServer CreateTestServer() { IWebHostBuilder hostBuilder = new WebHostBuilder() .ConfigureServices(services => { services.AddRouting(); BewitPayloadContext context = new BewitPayloadContext(typeof(string)) .SetCryptographyService(() => new HmacSha256CryptographyService(new BewitOptions { Secret = "123" })) .SetVariablesProvider(() => new MockedVariablesProvider()) .SetRepository(() => new DefaultNonceRepository()); services.AddTransient <IBewitTokenGenerator <string> >(ctx => new BewitTokenGenerator <string>(new BewitOptions(), context)); services .AddGraphQLServer() .SetOptions(new SchemaOptions { StrictValidation = false }) .AddMutationType(d => { d.Name("Mutation"); d.Field("RequestAccess") .Type <NonNullType <StringType> >() .Resolver(ctx => "foo") .UseBewitProtection <string>(); }); }) .Configure(app => app.UseRouting().UseEndpoints(e => e.MapGraphQL("/"))); return(new TestServer(hostBuilder)); }
public async Task ValidateBewitToken_WithPayload_ShouldReturnPayload() { //Arrange ICryptographyService cryptoService = MockHelper.GetMockedCrpytoService <Foo>(); var nonceRepository = new DefaultNonceRepository(); BewitPayloadContext context = new BewitPayloadContext(typeof(Foo)) .SetCryptographyService(() => cryptoService) .SetVariablesProvider(() => new MockHelper.MockedVariablesProvider()) .SetRepository(() => nonceRepository); var provider = new BewitTokenValidator <Foo>(context); var payload = new Foo { Bar = 1 }; var bewit = new Bewit <Foo>( "724e7acc-be57-49a1-8195-46a03c6271c6", new DateTime(2016, 1, 1, 1, 1, 1, 1, DateTimeKind.Utc), payload, "724e7acc-be57-49a1-8195-46a03c6271c6__2016-01-01T01:01:01.0010000Z__{\"Bar\":1}"); await nonceRepository.InsertOneAsync(bewit, default); var bewitToken = new BewitToken <Foo>( "eyJQYXlsb2FkIjp7IkJhciI6MX0sIkhhc2giOiI3MjRlN2FjYy1iZTU3LTQ5YTEtODE5NS00NmEwM2M2MjcxYzZfXzIwMTctMDEtMDFUMDE6MDI6MDEuMDAxMDAwMFpfX3tcIkJhclwiOjF9IiwiTm9uY2UiOiI3MjRlN2FjYy1iZTU3LTQ5YTEtODE5NS00NmEwM2M2MjcxYzYiLCJFeHBpcmF0aW9uRGF0ZSI6IjIwMTctMDEtMDFUMDE6MDI6MDEuMDAxWiJ9"); //Act Foo payload2 = await provider.ValidateBewitTokenAsync(bewitToken, CancellationToken.None); //Assert payload2.Bar.Should().Be(payload.Bar); }
public async Task OnAuthorization_WithDifferentUrl_ShouldNotAuthorize() { //Arrange var cryptoService = new HmacSha256CryptographyService(Options); TestServer server = TestServerHelper.CreateServer <string>(Options); var url = "/api/dummy/SomeBewitProtectedUrl"; BewitPayloadContext context = new BewitPayloadContext(typeof(string)) .SetCryptographyService(() => cryptoService) .SetVariablesProvider(() => TestServerHelper.VariablesProvider) .SetRepository(() => TestServerHelper.NonceRepository); var tokenGenerator = new BewitTokenGenerator <string>(Options, context); BewitToken <string> bewitToken = await tokenGenerator.GenerateBewitTokenAsync(url.ToLowerInvariant(), CancellationToken.None); url = "/api/dummy/WithBewitProtection"; var fullUrl = $"{url}?bewit={bewitToken}"; HttpClient client = server.CreateClient(); //Act HttpResponseMessage res = await client.GetAsync(fullUrl, CancellationToken.None); //Assert res.StatusCode.Should().Be(HttpStatusCode.Forbidden); var content = await res.Content.ReadAsStringAsync(); if (content != null) { Assert.Equal(-1, content.IndexOf("bar")); } }
public static void UseMongoPersistence( this BewitPayloadContext context, IConfiguration configuration) { MongoNonceOptions options = configuration .GetSection("Bewit:Mongo") .Get <MongoNonceOptions>(); context.UseMongoPersistence(options); }
public BewitTokenValidator(BewitPayloadContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } _cryptographyService = context.CreateCryptographyService?.Invoke() ?? throw new ArgumentNullException(nameof(BewitPayloadContext.CreateCryptographyService)); _variablesProvider = context.CreateVariablesProvider?.Invoke() ?? throw new ArgumentNullException(nameof(BewitPayloadContext.CreateVariablesProvider)); _repository = context.CreateRepository?.Invoke() ?? throw new ArgumentNullException(nameof(BewitPayloadContext.CreateRepository)); }
public async Task OnAuthorization_WithAlteredPayloadForUrl_ShouldNotAuthorize() { //Arrange var cryptoService = new HmacSha256CryptographyService(Options); TestServer server = TestServerHelper.CreateServer <string>(Options); var url = "/api/dummy/SomeBewitProtectedUrl"; BewitPayloadContext context = new BewitPayloadContext(typeof(string)) .SetCryptographyService(() => cryptoService) .SetVariablesProvider(() => TestServerHelper.VariablesProvider) .SetRepository(() => TestServerHelper.NonceRepository); var tokenGenerator = new BewitTokenGenerator <string>(Options, context); BewitToken <string> bewitToken = await tokenGenerator.GenerateBewitTokenAsync(url.ToLowerInvariant(), CancellationToken.None); //try to hack the token by replacing the url but reusing the same hash url = "/api/dummy/WithBewitProtection"; var serializedBewit = Encoding.UTF8.GetString(Convert.FromBase64String((string)bewitToken)); Bewit <string> bewitInternal = JsonConvert.DeserializeObject <Bewit <string> >(serializedBewit); var newBewitInternal = new Bewit <string>( bewitInternal.Nonce, bewitInternal.ExpirationDate, url.ToLowerInvariant(), bewitInternal.Hash); serializedBewit = JsonConvert.SerializeObject(newBewitInternal); bewitToken = new BewitToken <string>(Convert.ToBase64String( Encoding.UTF8.GetBytes(serializedBewit) )); var fullUrl = $"{url}?bewit={bewitToken}"; HttpClient client = server.CreateClient(); //Act HttpResponseMessage res = await client.GetAsync(fullUrl, CancellationToken.None); //Assert res.StatusCode.Should().Be(HttpStatusCode.Forbidden); var content = await res.Content.ReadAsStringAsync(); if (content != null) { Assert.Equal(-1, content.IndexOf("bar")); } }
public void Constructor_WithAllMandatoryOptions_ShouldInit() { //Arrange ICryptographyService cryptoService = MockHelper.GetMockedCrpytoService <Foo>(); BewitPayloadContext context = new BewitPayloadContext(typeof(string)) .SetCryptographyService(() => cryptoService) .SetVariablesProvider(() => new MockHelper.MockedVariablesProvider()) .SetRepository(() => new DefaultNonceRepository()); //Act var provider = new BewitTokenGenerator <Foo>(new BewitOptions(), context); //Assert provider.Should().NotBeNull(); }
public static void UseMongoPersistence( this BewitPayloadContext context, MongoNonceOptions options) { options.Validate(); if (context == null) { throw new ArgumentNullException(nameof(context)); } context.SetRepository(() => { var client = new MongoClient(options.ConnectionString); IMongoDatabase database = client.GetDatabase(options.DatabaseName); return(new MongoNonceRepository(database, options)); }); }
public async Task ValidateBewitTokenAsync_WithLegitPayload_ShouldStoreNonceAndReturnBewitToken() { //Arrange Token insertedToken = Token.Create("724e7acc-be57-49a1-8195-46a03c6271c6", DateTime.MaxValue); var repository = new Mock <INonceRepository>(); repository .Setup(r => r.TakeOneAsync(It.IsAny <string>(), It.IsAny <CancellationToken>())) .Returns((string tok, CancellationToken c) => { if (tok == insertedToken.Nonce) { Token tmpToken = insertedToken; insertedToken = null; return(new ValueTask <Token>(tmpToken)); } return(new ValueTask <Token>((Token)null)); }); BewitPayloadContext context = new BewitPayloadContext(typeof(Bar)) .SetCryptographyService(MockHelper.GetMockedCrpytoService <Bar>) .SetVariablesProvider(() => new MockHelper.MockedVariablesProvider()) .SetRepository(() => repository.Object); var provider = new BewitTokenValidator <Bar>(context); var payload = new Bar { Baz = "foo" }; BewitToken <Bar> token = new BewitToken <Bar>("eyJQYXlsb2FkIjp7IkJheiI6ImZvbyJ9LCJIYXNoIjoiNzI0ZTdhY2MtYmU1Ny00OWExLTgxOTUtNDZhMDNjNjI3MWM2X18yMDE3LTAxLTAxVDAxOjAyOjAxLjAwMTAwMDBaX197XCJCYXpcIjpcImZvb1wifSIsIk5vbmNlIjoiNzI0ZTdhY2MtYmU1Ny00OWExLTgxOTUtNDZhMDNjNjI3MWM2IiwiRXhwaXJhdGlvbkRhdGUiOiIyMDE3LTAxLTAxVDAxOjAyOjAxLjAwMVoifQ=="); //Act Bar payload2 = await provider.ValidateBewitTokenAsync( token, CancellationToken.None); //Assert payload2.Should().NotBeNull(); payload2.Should().NotBe(payload); payload2.Should().BeEquivalentTo(payload); }
public void UseMongoPersistence_WithBuilderNull_ShouldThrowArgumentNullException() { //Arrange BewitPayloadContext context = null; IMongoCollection <Foo> collection = _mongoResource.CreateCollection <Foo>(); //Act Action useRepository = () => context.UseMongoPersistence( new MongoNonceOptions { ConnectionString = _mongoResource.ConnectionString, DatabaseName = collection.Database.DatabaseNamespace.DatabaseName } ); //Assert useRepository.Should().Throw <ArgumentNullException>(); }
public void UseMongoPersistence_WithOnlyMandatoryParameters_ShouldInitAndReturnMongoNonceRepository() { //Arrange var builder = new BewitPayloadContext(typeof(object)); IMongoCollection <Foo> collection = _mongoResource.CreateCollection <Foo>(); //Act builder.UseMongoPersistence( new MongoNonceOptions { ConnectionString = _mongoResource.ConnectionString, DatabaseName = collection.Database.DatabaseNamespace.DatabaseName } ); //Assert builder.Should().Be(builder); builder.CreateRepository.Should().NotBeNull(); }
public void GenerateBewitTokenAsync_WithNullPayload_ShouldThrow() { //Arrange ICryptographyService cryptoService = MockHelper.GetMockedCrpytoService <Foo>(); BewitPayloadContext context = new BewitPayloadContext(typeof(string)) .SetCryptographyService(() => cryptoService) .SetVariablesProvider(() => new MockHelper.MockedVariablesProvider()) .SetRepository(() => new DefaultNonceRepository()); var provider = new BewitTokenGenerator <Foo>(new BewitOptions(), context); //Act Func <Task> generateBewit = async() => await provider.GenerateBewitTokenAsync(null, CancellationToken.None); //Assert generateBewit.Should().Throw <ArgumentNullException>(); }
public void UseMongoPersistence_WithMissingDatabaseNameInConfiguration_ShouldInitAndReturnMongoNonceRepository() { //Arrange var builder = new BewitPayloadContext(typeof(object)); IMongoCollection <Foo> collection = _mongoResource.CreateCollection <Foo>(); IConfiguration configuration = new ConfigurationBuilder() .AddInMemoryCollection(new[] { new KeyValuePair <string, string>("Bewit:Mongo:ConnectionString", _mongoResource.ConnectionString), new KeyValuePair <string, string>("Bewit:Mongo:sefef", collection.Database.DatabaseNamespace.DatabaseName), }) .Build(); //Act Action builder2 = () => builder.UseMongoPersistence(configuration); //Assert builder2.Should().Throw <ArgumentException>(); }
public BewitTokenGenerator( BewitOptions options, BewitPayloadContext context) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } _tokenDuration = options.TokenDuration; _cryptographyService = context.CreateCryptographyService?.Invoke() ?? throw new ArgumentNullException(nameof(BewitPayloadContext.CreateCryptographyService)); _variablesProvider = context.CreateVariablesProvider?.Invoke() ?? throw new ArgumentNullException(nameof(BewitPayloadContext.CreateVariablesProvider)); _repository = context.CreateRepository?.Invoke() ?? throw new ArgumentNullException(nameof(BewitPayloadContext.CreateRepository)); }
public void UseMongoPersistence_WithValidConfiguration_ShouldInitAndReturnMongoNonceRepository() { //Arrange var builder = new BewitPayloadContext(typeof(object)); IMongoCollection <Foo> collection = _mongoResource.CreateCollection <Foo>(); IConfiguration configuration = new ConfigurationBuilder() .AddInMemoryCollection(new[] { new KeyValuePair <string, string>("Bewit:Mongo:ConnectionString", _mongoResource.ConnectionString), new KeyValuePair <string, string>("Bewit:Mongo:DatabaseName", collection.Database.DatabaseNamespace.DatabaseName), }) .Build(); //Act builder.UseMongoPersistence(configuration); //Assert builder.Should().Be(builder); builder.CreateRepository.Should().NotBeNull(); }
public async Task GenerateBewitTokenAsync_WithDifferentPayload_ShouldGenerateBewit() { //Arrange ICryptographyService cryptoService = MockHelper.GetMockedCrpytoService <Foo>(); BewitPayloadContext context = new BewitPayloadContext(typeof(string)) .SetCryptographyService(() => cryptoService) .SetVariablesProvider(() => new MockHelper.MockedVariablesProvider()) .SetRepository(() => new DefaultNonceRepository()); var provider = new BewitTokenGenerator <Foo>(new BewitOptions(), context); var payload = new Foo { Bar = 5 }; //Act BewitToken <Foo> bewit = await provider.GenerateBewitTokenAsync(payload, CancellationToken.None); //Assert ((string)bewit).Should().Be("eyJQYXlsb2FkIjp7IkJhciI6NX0sIkhhc2giOiI3MjRlN2FjYy1iZTU3LTQ5YTEtODE5NS00NmEwM2M2MjcxYzZfXzIwMTctMDEtMDFUMDE6MDI6MDEuMDAxMDAwMFpfX3tcIkJhclwiOjV9IiwiTm9uY2UiOiI3MjRlN2FjYy1iZTU3LTQ5YTEtODE5NS00NmEwM2M2MjcxYzYiLCJFeHBpcmF0aW9uRGF0ZSI6IjIwMTctMDEtMDFUMDE6MDI6MDEuMDAxWiJ9"); }
public async Task OnAuthorization_WithValidBewitForUrl_ShouldAuthorize() { //Arrange TestServer server = TestServerHelper.CreateServer <IDictionary <string, object> >(Options); BewitPayloadContext context = new BewitPayloadContext(typeof(IDictionary <string, object>)) .SetCryptographyService(() => new HmacSha256CryptographyService(Options)) .SetVariablesProvider(() => TestServerHelper.VariablesProvider) .SetRepository(() => TestServerHelper.NonceRepository); var tokenGenerator = new BewitTokenGenerator <IDictionary <string, object> >(Options, context); const string id = "1", firstName = "John", lastName = "Smith"; var payload = new Dictionary <string, object> { ["firstName"] = "John", ["lastName"] = "Smith" }; BewitToken <IDictionary <string, object> > bewitToken = await tokenGenerator.GenerateBewitTokenAsync( payload, CancellationToken.None); var url = $"/api/dummy/WithBewitParameters/{id}"; var fullUrl = $"{url}?bewit={bewitToken}"; HttpClient client = server.CreateClient(); //Act HttpResponseMessage res = await client.GetAsync(fullUrl, CancellationToken.None); //Assert res.StatusCode.Should().Be(HttpStatusCode.OK); var content = await res.Content.ReadAsStringAsync(); content.Should().Be($"{id}: {firstName} {lastName}"); }