public async Task <IActionResult> Authenticate( [FromQuery()] AuthResourceModel resourceModel, [FromBody] AuthCredentialModel credentialModel) { resourceModel = resourceModel ?? new AuthResourceModel(); credentialModel = credentialModel ?? new AuthCredentialModel(); // Create command from the submitted models and send to application layer: var command = new AuthenticateCaller(credentialModel, resourceModel); AuthResult authResult = await _messagingSrv.SendAsync(command); // Based on the result, set the HTTP response code, response header and body: if (authResult.IsInvalidCredentialContext) { return(BadRequest(authResult.Reason)); } if (!authResult.IsAuthenticated) { return(Unauthorized()); } var resource = IdentityAuthResource.FromResult(command, authResult); return(new OkJwtAuthResult(authResult.JwtSignedToken, resource)); }
public async Task SpecifiedCredentials_MustPassProviderValidations() { // Arrange: var resourceModel = new AuthResourceModel { }; var credentialModel = new AuthCredentialModel { Api = "service-api", Credentials = new Dictionary <string, string> { } }; var command = new AuthenticateCaller(credentialModel, resourceModel); // Assume provider also indicates invalid submitted authentication request. var port = CreatePort(p => { p.IsValidRequest = false; p.HavingResult = c => throw new InvalidOperationException("Should be called for invalid request credentials"); }); // Act:IAuthProvider var result = await port.AuthenticateForService(command); // Assert: Assert.NotNull(result); Assert.True(result.IsInvalidCredentialContext); Assert.False(result.IsAuthenticated); }
public async Task ProviderResultsReturned_ForValidCredentials() { // Arrange: var resourceModel = new AuthResourceModel { }; var credentialModel = new AuthCredentialModel { Api = "service-api", Credentials = new Dictionary <string, string> { } }; var command = new AuthenticateCaller(credentialModel, resourceModel); // Create mock token service to return know token value var tokenSrv = new MockTokenService { ExpectedTokenValue = Guid.NewGuid().ToString() }; // Assume provider also indicates valid submitted authentication request. var port = CreatePort(p => { p.IsValidRequest = true; p.HavingResult = c => AuthResult.Authenticated(); }, tokenSrv); // Act: var result = await port.AuthenticateForService(command); // Assert: Assert.NotNull(result); Assert.False(result.IsInvalidCredentialContext); Assert.True(result.IsAuthenticated); Assert.Equal(tokenSrv.ExpectedTokenValue, result.JwtSignedToken); }
/// <summary> /// Command constructor. /// </summary> /// <param name="credentialModel">Model containing information about the service API requesting /// authentication and a set of key value pairs identifying the caller.</param> /// <param name="resourceModel">Model containing information about the resource for which access /// is being requested.</param> public AuthenticateCaller( AuthCredentialModel credentialModel, AuthResourceModel resourceModel) { Context = AuthContext.FromService(credentialModel.Api, credentialModel.Credentials); if (resourceModel.IsResourceAccessRequest) { Context = Context.ForResource(resourceModel.Service, resourceModel.Scope); } }
public async Task ResourcesToAuthenticateAccess_Received() { // Arrange: var mockMessaging = MockMessagingService.Setup(results => { var expectedResult = AuthResult.Authenticated().SetSignedToken("MOCK_TOKEN"); results.RegisterResponse <AuthenticateCaller, AuthResult>(expectedResult); }); var expectedService = "resource-owner"; var scope1 = "repository:test/my-app:pull,push"; var scope2 = "repository:test/my-app2:pull"; var url = $@"api/boondocks/authentication?service={expectedService}&scope={scope1}&scope={scope2}"; var plugin = new MockAppHostPlugin(); var httpClient = TestHttpClient.Create(plugin, mockMessaging); // Act: var credentials = new AuthCredentialModel { }; var result = await httpClient.AuthenticateAsync(url, credentials); // Assert: Assert.True(mockMessaging.ReceivedMessages.Count() == 1); var receivedCommand = (AuthenticateCaller)mockMessaging.ReceivedMessages.First(); Assert.NotNull(receivedCommand.Context); // Assert Owning Service Submitted: Assert.Equal(receivedCommand.Context.ResourceOwner, expectedService); // Assert Resources to Authenticate Access: Assert.NotNull(receivedCommand.Context.Resources); Assert.True(receivedCommand.Context.Resources.Length == 2); // Assert First Resource Scope: var firstScope = receivedCommand.Context.Resources[0]; Assert.Equal("repository", firstScope.Type); Assert.Equal("test/my-app", firstScope.Name); Assert.True(firstScope.Actions.Length == 2); Assert.Equal("pull", firstScope.Actions[0]); Assert.Equal("push", firstScope.Actions[1]); // Assert Second Resource Scope: var secondScope = receivedCommand.Context.Resources[1]; Assert.Equal("repository", secondScope.Type); Assert.Equal("test/my-app2", secondScope.Name); Assert.True(secondScope.Actions.Length == 1); Assert.Equal("pull", firstScope.Actions[0]); }
/// <summary> /// Authenticate using specified credentials. /// </summary> /// <param name="httpClient">>The HTTP client to use to make request.</param> /// <param name="uri">The URL to invoke.</param> /// <param name="credentialModel">The model containing the authentication credentials.</param> /// <returns>Response of the API call.</param> /// <returns></returns> public static Task <HttpResponseMessage> AuthenticateAsync(this HttpClient httpClient, string uri, AuthCredentialModel credentialModel) { var content = JsonConvert.SerializeObject(credentialModel); var buffer = System.Text.Encoding.UTF8.GetBytes(content); var byteContent = new ByteArrayContent(buffer); byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); return(httpClient.PostAsync(uri, byteContent)); }
public async Task ResourceContextSet_WhenSpecified() { // Arrange: var resourceModel = new AuthResourceModel { Service = "resource-owner", Scope = new string[] { @"repository:test/my-app:pull,push", @"repository:test/my-app2:pull" } }; var credentialModel = new AuthCredentialModel { Api = "service-api", Credentials = new Dictionary <string, string>() }; var command = new AuthenticateCaller(credentialModel, resourceModel); // Have the provider responded with a valid request var provider = new MockProvider { IsValidRequest = true }; var port = CreatePort(provider); // Act: var result = await port.AuthenticateForService(command); // Assert: Assert.NotNull(provider.ReceivedContext); Assert.Equal("resource-owner", provider.ReceivedContext.ResourceOwner); Assert.True(provider.ReceivedContext.Resources.Length == 2); var firstResourceScope = provider.ReceivedContext.Resources[0]; var secondResourceScope = provider.ReceivedContext.Resources[1]; // Assert first resource scope: Assert.Equal("repository", firstResourceScope.Type); Assert.Equal("test/my-app", firstResourceScope.Name); Assert.True(firstResourceScope.Actions.Length == 2); Assert.Equal("pull", firstResourceScope.Actions[0]); Assert.Equal("push", firstResourceScope.Actions[1]); // Assert second resource scope: Assert.Equal("repository", secondResourceScope.Type); Assert.Equal("test/my-app2", secondResourceScope.Name); Assert.True(secondResourceScope.Actions.Length == 1); Assert.Equal("pull", secondResourceScope.Actions[0]); }
public async Task InvalidSpecifiedCredentials_UnAuthorized() { // Arrange: var mockMessaging = MockMessagingService.Setup(results => { var expectedResult = AuthResult.SetAuthenticated(false); results.RegisterResponse <AuthenticateCaller, AuthResult>(expectedResult); }); var plugin = new MockAppHostPlugin(); var httpClient = TestHttpClient.Create(plugin, mockMessaging); // Act: var credentials = new AuthCredentialModel { }; var result = await httpClient.AuthenticateAsync(credentials); // Assert: Assert.Equal(HttpStatusCode.Unauthorized, result.StatusCode); }
public async Task Credentials_MustBeSpecified() { // Arrange: var resourceModel = new AuthResourceModel { }; var credentialModel = new AuthCredentialModel { Api = "service-api", Credentials = null }; var command = new AuthenticateCaller(credentialModel, resourceModel); var port = CreatePort(p => { }); // Act: var result = await port.AuthenticateForService(command); // Assert: Assert.NotNull(result); Assert.True(result.IsInvalidCredentialContext); Assert.Equal("Invalid authentication context and/or credentials.", result.Reason); Assert.False(result.IsAuthenticated); }
public async Task ClientCredentialsReceived_WhenSent() { // Arrange: var mockMessaging = MockMessagingService.Setup(results => { var expectedResult = AuthResult.Authenticated().SetSignedToken("MOCK_TOKEN"); results.RegisterResponse <AuthenticateCaller, AuthResult>(expectedResult); }); var plugin = new MockAppHostPlugin(); var httpClient = TestHttpClient.Create(plugin, mockMessaging); // Act: var credentialModle = new AuthCredentialModel { Credentials = new Dictionary <string, string> { { "CertKey1", "CertValue1" }, { "CertKey2", "CertValue2" } } }; var result = await httpClient.AuthenticateAsync(credentialModle); // Assert: Assert.True(mockMessaging.ReceivedMessages.Count() == 1); var receivedCommand = (AuthenticateCaller)mockMessaging.ReceivedMessages.First(); Assert.NotNull(receivedCommand.Context); var receivedCredentials = receivedCommand.Context.Credentials; Assert.NotNull(receivedCredentials); Assert.True(receivedCredentials.ContainsKey("CertKey1")); Assert.True(receivedCredentials.ContainsKey("CertKey2")); Assert.Equal("CertValue1", receivedCredentials["CertKey1"]); Assert.Equal("CertValue2", receivedCredentials["CertKey2"]); }
public async Task ValidCredentials_ResourceAccess_Returned() { // Arrange: var allowedResourceAccess = new ResourcePermission[] { new ResourcePermission(type: "ResourceType", name: "ResourceName", actions: new string[] { "action1", "action2" }) }; var mockMessaging = MockMessagingService.Setup(results => { var expectedResult = AuthResult.Authenticated(allowedResourceAccess) .SetSignedToken("MOCK_TOKEN"); results.RegisterResponse <AuthenticateCaller, AuthResult>(expectedResult); }); var plugin = new MockAppHostPlugin(); var httpClient = TestHttpClient.Create(plugin, mockMessaging); // Act: var credentials = new AuthCredentialModel { }; var result = await httpClient.AuthenticateAsync(credentials); // Assert: var responseValue = await result.Content.ReadAsStringAsync(); var resource = JsonConvert.DeserializeObject <AuthResultResource>(responseValue); var resourcesGrantedAccess = resource.GetEmbeddedCollection <AuthAccessResource>("resource-access"); Assert.NotNull(resourcesGrantedAccess); Assert.True(resourcesGrantedAccess.Count() == 1); var access = resourcesGrantedAccess.First(); Assert.Equal("ResourceType", access.Type); Assert.Equal("ResourceName", access.Name); Assert.True(access.Actions.Length == 2); Assert.Equal("action1", access.Actions[0]); Assert.Equal("action2", access.Actions[1]); }
public async Task ValidCredentials_OkStatus_WithTokenHeader() { // Arrange: var mockMessaging = MockMessagingService.Setup(results => { var expectedResult = AuthResult.Authenticated() .SetSignedToken("MOCK_TOKEN"); results.RegisterResponse <AuthenticateCaller, AuthResult>(expectedResult); }); var plugin = new MockAppHostPlugin(); var httpClient = TestHttpClient.Create(plugin, mockMessaging); // Act: var credentials = new AuthCredentialModel { }; var result = await httpClient.AuthenticateAsync(credentials); // Assert: Assert.Equal(HttpStatusCode.OK, result.StatusCode); result.Headers.TryGetValues("X-Custom-Token", out IEnumerable <string> values); Assert.True(values.Count() == 1); Assert.Equal("MOCK_TOKEN", values.First()); }
public async Task IncorrectedOrMissingCredentials_BadRequest() { // Arrange: var mockMessaging = MockMessagingService.Setup(results => { var expectedResult = AuthResult.Failed("INVALID_CONTEXT"); results.RegisterResponse <AuthenticateCaller, AuthResult>(expectedResult); }); var plugin = new MockAppHostPlugin(); var httpClient = TestHttpClient.Create(plugin, mockMessaging); // Act: var credentials = new AuthCredentialModel { }; var result = await httpClient.AuthenticateAsync(credentials); // Assert: Assert.Equal(HttpStatusCode.BadRequest, result.StatusCode); Assert.NotNull(result.Content); var content = await result.Content.ReadAsStringAsync(); Assert.Equal("INVALID_CONTEXT", content); }
/// <summary> /// Authenticate using specified credentials. /// </summary> /// <param name="httpClient">The HTTP client to use to make request.</param> /// <param name="credentialModel">The model containing the authentication credentials.</param> /// <returns>Response of the API call.</returns> public static Task <HttpResponseMessage> AuthenticateAsync(this HttpClient httpClient, AuthCredentialModel credentialModel) { return(httpClient.AuthenticateAsync("api/boondocks/authentication", credentialModel)); }