# Task 4: Create Auth Controller ## Task Description **Files:** - Create: `src/Fengling.AuthService/Controllers/AuthController.cs` - Create: `src/Fengling.AuthService/DTOs/LoginRequest.cs` - Create: `src/Fengling.AuthService/DTOs/LoginResponse.cs` - Create: `src/Fengling.AuthService/DTOs/TokenResponse.cs` ## Implementation Steps ### Step 1: Create DTOs Create: `src/Fengling.AuthService/DTOs/LoginRequest.cs` ```csharp namespace Fengling.AuthService.DTOs; public class LoginRequest { public string UserName { get; set; } = string.Empty; public string Password { get; set; } = string.Empty; public long TenantId { get; set; } } ``` Create: `src/Fengling.AuthService/DTOs/LoginResponse.cs` ```csharp namespace Fengling.AuthService.DTOs; public class LoginResponse { public string AccessToken { get; set; } = string.Empty; public string RefreshToken { get; set; } = string.Empty; public int ExpiresIn { get; set; } public string TokenType { get; set; } = "Bearer"; } ``` ### Step 2: Create AuthController Create: `src/Fengling.AuthService/Controllers/AuthController.cs` ```csharp using Fengling.AuthService.DTOs; using Fengling.AuthService.Models; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using OpenIddict.Abstractions; using OpenIddict.Server.AspNetCore; using static OpenIddict.Abstractions.OpenIddictConstants; namespace Fengling.AuthService.Controllers; [ApiController] [Route("api/[controller]")] public class AuthController : ControllerBase { private readonly SignInManager _signInManager; private readonly UserManager _userManager; private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictAuthorizationManager _authorizationManager; private readonly IOpenIddictScopeManager _scopeManager; private readonly ILogger _logger; public AuthController( SignInManager signInManager, UserManager userManager, IOpenIddictApplicationManager applicationManager, IOpenIddictAuthorizationManager authorizationManager, IOpenIddictScopeManager scopeManager, ILogger logger) { _signInManager = signInManager; _userManager = userManager; _applicationManager = applicationManager; _authorizationManager = authorizationManager; _scopeManager = scopeManager; _logger = logger; } [HttpPost("login")] public async Task Login([FromBody] LoginRequest request) { var user = await _userManager.FindByNameAsync(request.UserName); if (user == null || user.IsDeleted) { return Unauthorized(new { error = "用户不存在" }); } if (user.TenantId != request.TenantId) { return Unauthorized(new { error = "租户不匹配" }); } var result = await _signInManager.CheckPasswordSignInAsync(user, request.Password, false); if (!result.Succeeded) { return Unauthorized(new { error = "用户名或密码错误" }); } var token = await GenerateTokenAsync(user); return Ok(token); } private async Task GenerateTokenAsync(ApplicationUser user) { var claims = new List { new(Claims.Subject, user.Id.ToString()), new(Claims.Name, user.UserName ?? string.Empty), new(Claims.Email, user.Email ?? string.Empty), new("tenant_id", user.TenantId.ToString()) }; var roles = await _userManager.GetRolesAsync(user); foreach (var role in roles) { claims.Add(new Claim(Claims.Role, role)); } var identity = new System.Security.Claims.ClaimsIdentity(claims, "Server"); var principal = new System.Security.Claims.ClaimsPrincipal(identity); return new LoginResponse { AccessToken = "token-placeholder", RefreshToken = "refresh-placeholder", ExpiresIn = 3600, TokenType = "Bearer" }; } } ``` ### Step 3: Run to verify controller compilation Run: ```bash dotnet build ``` Expected: Build succeeds ### Step 4: Commit ```bash git add src/Fengling.AuthService/Controllers/ src/Fengling.AuthService/DTOs/ git commit -m "feat(auth): add authentication controller with login endpoint" ``` ## Context This task creates an authentication controller with a login endpoint. The login endpoint validates user credentials, checks tenant isolation, and generates JWT tokens with embedded tenant_id claims for multi-tenant routing. **Tech Stack**: ASP.NET Core Controllers, OpenIddict ## Verification - [ ] LoginRequest DTO created - [ ] LoginResponse DTO created - [ ] AuthController created with login endpoint - [ ] Tenant validation implemented - [ ] Build succeeds - [ ] Committed to git ## Notes - Token generation is placeholder, will be replaced by OpenIddict in next task - Tenant validation ensures multi-tenant isolation