/** * Authentication Response DTO * * Data transfer object for authentication responses. * Contains authentication tokens, user information, * and security status after successful login. * * @author David Valera Melendez * @since February 2025 */ package com.company.auth.dto.response; import io.swagger.v3.oas.annotations.media.Schema; import com.fasterxml.jackson.annotation.JsonInclude; import java.time.LocalDateTime; /** * Response DTO for authentication operations * * Provides authentication tokens, user details, and security * information after successful login or registration. */ @Schema(description = "Authentication response data") @JsonInclude(JsonInclude.Include.NON_NULL) public class AuthResponse { /** * JWT access token * * Short-lived token for API authentication. * Should be included in Authorization header. */ @Schema(description = "JWT access token for API authentication") private String accessToken; /** * JWT refresh token * * Long-lived token for obtaining new access tokens. * Should be stored securely on the client. */ @Schema(description = "JWT refresh token for token renewal") private String refreshToken; /** * Token type * * Type of the access token, typically "Bearer". */ @Schema(description = "Token type", example = "Bearer") private String tokenType = "Bearer"; /** * Token expiration time * * Timestamp when the access token expires. * Client should refresh before this time. */ @Schema(description = "Access token expiration time") private LocalDateTime expiresAt; /** * User information * * Basic user profile information for the * authenticated user. */ @Schema(description = "Authenticated user information") private UserResponse user; /** * Two-factor authentication required * * Indicates if 2FA verification is required * to complete the authentication process. */ @Schema(description = "Whether 2FA verification is required", example = "false") private Boolean requiresTwoFactor = false; /** * Device verification required * * Indicates if device verification is required * for this login attempt. */ @Schema(description = "Whether device verification is required", example = "false") private Boolean requiresDeviceVerification = false; /** * Session token for multi-step authentication * * Temporary token for completing multi-step * authentication processes (2FA, device verification). */ @Schema(description = "Temporary session token for multi-step auth") private String sessionToken; /** * Available 2FA methods * * List of 2FA methods available to the user * when 2FA is required. */ @Schema(description = "Available 2FA methods", example = "[\"totp\", \"sms\"]") private String[] availableTwoFactorMethods; /** * Device trust status * * Indicates the trust level of the current device. */ @Schema(description = "Current device trust status", example = "trusted") private String deviceTrustStatus; /** * Login timestamp * * Timestamp when the authentication occurred. */ @Schema(description = "Login timestamp") private LocalDateTime loginAt; /** * IP address of the login * * IP address from which the authentication * was performed. */ @Schema(description = "IP address of the login", example = "192.168.1.100") private String ipAddress; /** * New device detected flag * * Indicates if this login was from a new/unknown device. */ @Schema(description = "Whether this is a new device", example = "false") private Boolean isNewDevice = false; /** * Security alerts count * * Number of pending security alerts for the user. */ @Schema(description = "Number of pending security alerts", example = "0") private Integer securityAlertsCount = 0; /** * Last login information * * Information about the user's previous login * for security awareness. */ @Schema(description = "Previous login information") private LastLoginInfo lastLogin; /** * Default constructor */ public AuthResponse() { this.loginAt = LocalDateTime.now(); } /** * Constructor for successful authentication * * @param accessToken JWT access token * @param refreshToken JWT refresh token * @param expiresAt Token expiration time * @param user User information */ public AuthResponse(String accessToken, String refreshToken, LocalDateTime expiresAt, UserResponse user) { this(); this.accessToken = accessToken; this.refreshToken = refreshToken; this.expiresAt = expiresAt; this.user = user; } /** * Constructor for multi-step authentication * * @param sessionToken Temporary session token * @param requiresTwoFactor Whether 2FA is required * @param requiresDeviceVerification Whether device verification is required */ public AuthResponse(String sessionToken, Boolean requiresTwoFactor, Boolean requiresDeviceVerification) { this(); this.sessionToken = sessionToken; this.requiresTwoFactor = requiresTwoFactor; this.requiresDeviceVerification = requiresDeviceVerification; } /** * Creates a successful authentication response * * @param accessToken JWT access token * @param refreshToken JWT refresh token * @param expiresAt Token expiration * @param user User information * @return AuthResponse instance */ public static AuthResponse success(String accessToken, String refreshToken, LocalDateTime expiresAt, UserResponse user) { return new AuthResponse(accessToken, refreshToken, expiresAt, user); } /** * Creates a response requiring 2FA * * @param sessionToken Temporary session token * @param availableMethods Available 2FA methods * @return AuthResponse instance */ public static AuthResponse requireTwoFactor(String sessionToken, String[] availableMethods) { AuthResponse response = new AuthResponse(sessionToken, true, false); response.setAvailableTwoFactorMethods(availableMethods); return response; } /** * Creates a response requiring device verification * * @param sessionToken Temporary session token * @return AuthResponse instance */ public static AuthResponse requireDeviceVerification(String sessionToken) { return new AuthResponse(sessionToken, false, true); } /** * Checks if authentication is complete * * @return true if user is fully authenticated */ public boolean isAuthenticationComplete() { return accessToken != null && !requiresTwoFactor && !requiresDeviceVerification; } /** * Checks if additional verification is needed * * @return true if more steps are required */ public boolean requiresAdditionalVerification() { return requiresTwoFactor || requiresDeviceVerification; } // Getters and Setters public String getAccessToken() { return accessToken; } public void setAccessToken(String accessToken) { this.accessToken = accessToken; } public String getRefreshToken() { return refreshToken; } public void setRefreshToken(String refreshToken) { this.refreshToken = refreshToken; } public String getTokenType() { return tokenType; } public void setTokenType(String tokenType) { this.tokenType = tokenType; } public LocalDateTime getExpiresAt() { return expiresAt; } public void setExpiresAt(LocalDateTime expiresAt) { this.expiresAt = expiresAt; } public UserResponse getUser() { return user; } public void setUser(UserResponse user) { this.user = user; } public Boolean getRequiresTwoFactor() { return requiresTwoFactor; } public void setRequiresTwoFactor(Boolean requiresTwoFactor) { this.requiresTwoFactor = requiresTwoFactor; } public Boolean getRequiresDeviceVerification() { return requiresDeviceVerification; } public void setRequiresDeviceVerification(Boolean requiresDeviceVerification) { this.requiresDeviceVerification = requiresDeviceVerification; } public String getSessionToken() { return sessionToken; } public void setSessionToken(String sessionToken) { this.sessionToken = sessionToken; } public String[] getAvailableTwoFactorMethods() { return availableTwoFactorMethods; } public void setAvailableTwoFactorMethods(String[] availableTwoFactorMethods) { this.availableTwoFactorMethods = availableTwoFactorMethods; } public String getDeviceTrustStatus() { return deviceTrustStatus; } public void setDeviceTrustStatus(String deviceTrustStatus) { this.deviceTrustStatus = deviceTrustStatus; } public LocalDateTime getLoginAt() { return loginAt; } public void setLoginAt(LocalDateTime loginAt) { this.loginAt = loginAt; } public String getIpAddress() { return ipAddress; } public void setIpAddress(String ipAddress) { this.ipAddress = ipAddress; } public Boolean getIsNewDevice() { return isNewDevice; } public void setIsNewDevice(Boolean isNewDevice) { this.isNewDevice = isNewDevice; } public Integer getSecurityAlertsCount() { return securityAlertsCount; } public void setSecurityAlertsCount(Integer securityAlertsCount) { this.securityAlertsCount = securityAlertsCount; } public LastLoginInfo getLastLogin() { return lastLogin; } public void setLastLogin(LastLoginInfo lastLogin) { this.lastLogin = lastLogin; } /** * Last login information nested class */ @Schema(description = "Previous login information") public static class LastLoginInfo { @Schema(description = "Previous login timestamp") private LocalDateTime timestamp; @Schema(description = "Previous login IP address") private String ipAddress; @Schema(description = "Previous login location") private String location; @Schema(description = "Previous login device") private String device; // Constructors public LastLoginInfo() {} public LastLoginInfo(LocalDateTime timestamp, String ipAddress, String location, String device) { this.timestamp = timestamp; this.ipAddress = ipAddress; this.location = location; this.device = device; } // Getters and Setters public LocalDateTime getTimestamp() { return timestamp; } public void setTimestamp(LocalDateTime timestamp) { this.timestamp = timestamp; } public String getIpAddress() { return ipAddress; } public void setIpAddress(String ipAddress) { this.ipAddress = ipAddress; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public String getDevice() { return device; } public void setDevice(String device) { this.device = device; } } }