EasyApp

Login and Sign Up

Learn how to implement login and sign up in your app

loginAndSignUp

Login and Sign Up Module

The LoginAndSignUp module is a complete user authentication solution, providing login, registration, forgot password, and email verification functionality.

We will provide more beautiful login and registration pages in the future, so stay tuned.

Module Structure

LoginAndSignUp/
├── View/
│   └── LoginAndSignUp.swift        # Main view, manages login/signup switching
└── SubPages/
    ├── SignIn/View/
    │   └── SignInView.swift        # Login interface
    ├── SignUp/View/
    │   └── SignUpView.swift        # Registration interface
    ├── ForgotPwd/View/
    │   └── ForgotPwdView.swift     # Forgot password
    └── VerifyEmailView/View/
        └── VerifyEmailView.swift   # Email verification

Core Features

1. Main View Switching

The main view uses state management to switch between login and registration interfaces, providing smooth sliding animations:

struct LoginAndSignUp: View {
    @State private var showSignUp = false
    
    var body: some View {
        if showSignUp {
            SignUpView(showSignIn: $showSignUp)
                .transition(.asymmetric(
                    insertion: .move(edge: .trailing), 
                    removal: .move(edge: .trailing)
                ))
        } else {
            SignInView(showSignUp: $showSignUp)
                .transition(.asymmetric(
                    insertion: .move(edge: .leading), 
                    removal: .move(edge: .leading)
                ))
        }
    }
}

2. Login Functionality

Supports two login methods:

  • Email and password login
  • Apple ID login

Key Features:

  • Real-time input validation (email format, password strength)
  • Forgot password link
  • Loading state indicators
  • Toast message notifications
func signInWithEmail() {
    Task {
        do {
            try await authManager.signIn(email: account, password: password)
        } catch {
            print("signInWithEmailError:\(error)")
        }
    }
}

func signInWithApple(idToken: String) {
    Task {
        do {
            try await authManager.signInWithApple(idToken: idToken)
        } catch {
            print("signInWithAppleError:\(error)")
        }
    }
}

3. Registration Functionality

Registration Flow:

  1. User enters email and password
  2. Real-time input format validation
  3. Submit registration request
  4. Automatically redirect to login page on success

Input Validation Rules:

  • Email format validation
  • Password length (6-12 characters)
  • Password must contain letters
func onSignUp() {
    Task {
        do {
            try await authManager.signUp(email: account, password: password)
        } catch {
            print("onSignUpError:\(error)")
        }
    }
}

4. Forgot Password

Provides password reset functionality, allowing users to:

  • Enter email address
  • Set new password
  • Validate input validity
  • Send reset request

5. Email Verification

When users need to verify their email after registration, displays verification interface:

  • Prompts user to check email
  • Provides resend verification email functionality
  • Monitors application state changes
Button(action: {
    isLoading = true
    Task {
        do {
            try await authManager.resendVerificationEmail(email: email)
            isLoading = false
        } catch {
            isLoading = false
        }
    }
}) {
    Text("resend_verification_email")
        .font(.title3)
}

Authentication Management

The module handles all authentication logic through AuthManager:

  • Supabase Integration: Uses Supabase as backend authentication service
  • State Management: Automatically manages user login state
  • Session Handling: Handles token refresh and expiration
  • Subscription Integration: Supports RevenueCat and StoreKit2

User Interface Features

1. Smooth Transitions

  • Sliding animations between login and registration
  • Loading state indicators
  • Visual feedback for user actions

2. Input Validation

  • Real-time email format checking
  • Password strength requirements
  • Clear error messaging

3. Apple Sign-In Integration

  • Native Apple ID authentication
  • Seamless user experience
  • Privacy-focused approach

4. Responsive Design

  • Adapts to different screen sizes
  • Keyboard-aware interface
  • Accessibility support

Authentication Flow

1. Login Process

struct SignInView: View {
    @EnvironmentObject private var authManager: AuthManager
    @State private var account = ""
    @State private var password = ""
    @State private var isLoading = false
    
    var body: some View {
        VStack(spacing: 20) {
            // Email input
            TextField("Email", text: $account)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .keyboardType(.emailAddress)
                .autocapitalization(.none)
            
            // Password input
            SecureField("Password", text: $password)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            
            // Sign in button
            Button("Sign In") {
                signInWithEmail()
            }
            .disabled(account.isEmpty || password.isEmpty || isLoading)
            
            // Apple Sign In
            SignInWithAppleButton { request in
                request.requestedScopes = [.fullName, .email]
            } onCompletion: { result in
                handleAppleSignIn(result)
            }
        }
    }
}

2. Registration Process

struct SignUpView: View {
    @EnvironmentObject private var authManager: AuthManager
    @State private var account = ""
    @State private var password = ""
    @State private var isLoading = false
    
    var body: some View {
        VStack(spacing: 20) {
            // Email input with validation
            TextField("Email", text: $account)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .keyboardType(.emailAddress)
                .autocapitalization(.none)
                .overlay(
                    RoundedRectangle(cornerRadius: 8)
                        .stroke(isValidEmail ? Color.green : Color.red, lineWidth: 1)
                )
            
            // Password input with strength indicator
            SecureField("Password", text: $password)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            
            PasswordStrengthIndicator(password: password)
            
            // Sign up button
            Button("Sign Up") {
                onSignUp()
            }
            .disabled(!isValidInput || isLoading)
        }
    }
    
    private var isValidEmail: Bool {
        account.contains("@") && account.contains(".")
    }
    
    private var isValidInput: Bool {
        isValidEmail && password.count >= 6 && password.count <= 12
    }
}

Error Handling

1. Authentication Errors

enum AuthError: LocalizedError {
    case invalidCredentials
    case emailNotVerified
    case networkError
    case unknownError(String)
    
    var errorDescription: String? {
        switch self {
        case .invalidCredentials:
            return "Invalid email or password"
        case .emailNotVerified:
            return "Please verify your email address"
        case .networkError:
            return "Network connection error"
        case .unknownError(let message):
            return message
        }
    }
}

2. User Feedback

.alert("Error", isPresented: $showError) {
    Button("OK") { }
} message: {
    Text(errorMessage)
}

.toast(isPresented: $showToast, message: toastMessage, isSuccess: isSuccess)

Security Features

1. Input Sanitization

private func sanitizeInput(_ input: String) -> String {
    return input.trimmingCharacters(in: .whitespacesAndNewlines)
}

private func validateEmail(_ email: String) -> Bool {
    let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
    let emailPredicate = NSPredicate(format:"SELF MATCHES %@", emailRegex)
    return emailPredicate.evaluate(with: email)
}

2. Password Requirements

private func validatePassword(_ password: String) -> Bool {
    return password.count >= 6 && 
           password.count <= 12 && 
           password.rangeOfCharacter(from: .letters) != nil
}

Best Practices

1. User Experience

// Provide immediate feedback
.onChange(of: account) { newValue in
    validateInput()
}

// Show loading states
.disabled(isLoading)
.overlay(
    ProgressView()
        .opacity(isLoading ? 1 : 0)
)

2. Accessibility

.accessibilityLabel("Email input field")
.accessibilityHint("Enter your email address")
.accessibilityIdentifier("emailTextField")

3. Keyboard Management

.onSubmit {
    if isValidInput {
        signInWithEmail()
    }
}
.submitLabel(.go)

Integration with Other Modules

1. Onboarding Integration

// Show onboarding for new users
if authManager.isAuthenticated && !hasCompletedOnboarding {
    OnboardingView()
}

2. Subscription Integration

// Check subscription status after login
.onReceive(authManager.$isAuthenticated) { isAuthenticated in
    if isAuthenticated {
        revenueCatManager.checkSubscriptionStatus()
    }
}

1. Multi-Authentication Support

  • Email/password authentication
  • Apple Sign-In integration
  • Social login extensibility

2. Real-time Validation

  • Input format checking
  • Password strength indicators
  • Immediate user feedback

3. Smooth User Experience

  • Animated transitions
  • Loading states
  • Toast notifications

4. Security First

  • Input sanitization
  • Secure password handling
  • Session management

The Login and Sign Up module provides a complete, secure, and user-friendly authentication system that integrates seamlessly with the rest of your EasyAppSwiftUI application.

Last updated on