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 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); }
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 static IdentityAuthResource FromResult(AuthenticateCaller command, AuthResult authResult) { var resource = new IdentityAuthResource { CorrelationId = command.GetCorrelationId(), IsAuthenticated = authResult.IsAuthenticated }; var accessResources = authResult.ResourcePermissions .Select(e => new AccessResource { Type = e.Type, Name = e.Name, Actions = e.Actions }).ToArray(); resource.Embed(accessResources, "resource-access") ; return(resource); }
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 <AuthResult> AuthenticateForService(AuthenticateCaller authCommand) { // Validate the submitted credentials required from all providers: ValidationResultSet validationResults = _validationSrv.Validate(authCommand); if (validationResults.IsInvalid) { _logger.LogErrorDetails( LogEvents.RequiredCredentialsError, "Invalid submitted context and/or credentials", validationResults); return(AuthResult.Failed("Invalid authentication context and/or credentials.")); } // Based on the service requesting the authentication token, lookup the associated provider. IAuthProvider provider = GetProvider(authCommand); if (provider == null) { return(AuthResult.Failed( $"Requests from Api: {authCommand.Context.RequestingApi} can't be authenticated.")); } // Delegate to the provider to determine if the submitted credentials are valid // for the service requesting the authentication token. if (!provider.IsValidAuthenticationRequest(authCommand.Context)) { return(AuthResult.Failed("Invalid Authentication Request")); } // Since valid credential values have been received, delegate to the provider // to preform the authentication. AuthResult authResult = await provider.OnAuthenticateAsync(authCommand.Context); authResult = SetTokenForAuthenticationRequest(authResult, provider); _logger.LogTraceDetails(LogEvents.AuthResultDetermined, "Authentication results determined by provider.", authResult); return(authResult); }
private IAuthProvider GetProvider(AuthenticateCaller authCommand) { // Delegate to the provider module to determine the provider associated with the service-API // requesting authentication. IAuthProvider provider = _providerModule.GetServiceAuthProvider(_lifetimeScope, authCommand.Context.RequestingApi); if (provider == null) { _logger.LogError(LogEvents.UnknownRequestingService, "Authentication Provider for Service not be Resolved: {ServiceName}", authCommand.Context.RequestingApi); return(null); } _logger.LogDebug(LogEvents.AuthProviderResolved, "Authentication for {ServiceName} being handled by Provider: {ProviderType}", authCommand.Context.RequestingApi, provider.GetType().FullName); return(provider); }
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); }