Handler.cs 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. using SharedKernel;
  2. using SharedKernel.Results;
  3. using Application.Abstractions.Authentication;
  4. using Application.Abstractions.Data;
  5. using MediatR;
  6. using Microsoft.EntityFrameworkCore;
  7. using Microsoft.Extensions.Options;
  8. namespace Application.Features.Api.Auth.RefreshToken;
  9. internal sealed class Handler(
  10. IAppDbContext db,
  11. IJwtTokenProvider jwtTokenProvider,
  12. IOptions<AppSettings> options
  13. ) : IRequestHandler<Command, Result<Response>> {
  14. private readonly AppSettings.JwtSection _jwt = options.Value.JWT;
  15. public async Task<Result<Response>> Handle(Command request, CancellationToken ct)
  16. {
  17. if (string.IsNullOrWhiteSpace(request.RefreshToken))
  18. {
  19. return Result.Failure<Response>(Error.Problem("Auth.TokenRequired", "refreshToken은 필수입니다."));
  20. }
  21. // 기존 RefreshToken 조회
  22. var existingToken = await db.RefreshToken.Include(x => x.Member).FirstOrDefaultAsync(x => x.Token == request.RefreshToken, ct);
  23. if (existingToken is null)
  24. {
  25. return Result.Failure<Response>(Error.NotFound("Auth.TokenNotFound", "유효하지 않은 refreshToken 입니다."));
  26. }
  27. if (!existingToken.IsActive)
  28. {
  29. return Result.Failure<Response>(Error.Problem("Auth.TokenExpired", "만료되었거나 취소된 refreshToken 입니다."));
  30. }
  31. if (existingToken.Member is null)
  32. {
  33. return Result.Failure<Response>(Error.NotFound("Auth.MemberNotFound", "회원 정보를 찾을 수 없습니다."));
  34. }
  35. var member = existingToken.Member;
  36. // 기존 토큰 폐기
  37. existingToken.Revoke();
  38. // 새 토큰 생성
  39. var accessToken = jwtTokenProvider.CreateAccessToken(member.ID, member.Email, member.Name);
  40. var newRefreshToken = jwtTokenProvider.CreateRefreshToken();
  41. var expiresAt = DateTime.UtcNow.AddMinutes(_jwt.AccessTokenExpiration);
  42. // 새 RefreshToken 저장
  43. var refreshTokenEntity = Domain.Entities.Members.RefreshToken.Create(
  44. member.ID,
  45. newRefreshToken,
  46. DateTime.UtcNow.AddDays(_jwt.RefreshTokenExpiration)
  47. );
  48. await db.RefreshToken.AddAsync(refreshTokenEntity, ct);
  49. await db.SaveChangesAsync(ct);
  50. return Result.Success(new Response(
  51. accessToken, newRefreshToken, expiresAt
  52. ));
  53. }
  54. }