Skip to content

A package that easily adds JWT and social auth + endpoints to your ASP.net core project with minimal efforts on your side.

License

Notifications You must be signed in to change notification settings

DamienDoumer/The.Jwt.Auth.Endpoints

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

The.Jwt.Auth.Endpoints

.NET ASP.NET Core License

A complete, production-ready JWT authentication library for ASP.NET Core applications. This library provides pre-built authentication endpoints using minimal APIs, following modern ASP.NET Core patterns and security best practices.

Why The.Jwt.Auth.Endpoints?

Microsoft released Identity endpoints as part of .NET 8, but with limitations: Uses proprietary tokens instead of standard JWT, and has limited customization.

This library provides the same functionality as Identity endpoints but with: Standard JWT tokens with more customization.

Installation

Just add the nugget package to your project (The.Jwt.Auth.Endpoints)

dotnet add package The.Jwt.Auth.Endpoints

Features

  • 🔐 Complete Authentication Flow: Login, registration, email confirmation, password reset
  • 🔄 JWT Token Management: Access tokens with refresh token support
  • 📧 Email Integration: Configurable email confirmation and password reset
  • 🌐 Google Social Auth: Optional Firebase Google authentication

API Endpoints

Once configured, the library provides the following endpoints:

Endpoint Method Description
/api/auth/register POST User registration with email confirmation
/api/auth/login POST User login with email/password
/api/auth/refresh POST Refresh JWT access token
/api/auth/confirmEmail GET Confirm user email address
/api/auth/forgotPassword POST Initiate password reset process
/api/auth/resetPassword POST Complete password reset
/api/auth/social/google POST Google Firebase authentication (optional)

Quick Start

1. Installation

dotnet add package The.Jwt.Auth.Endpoints

2. Basic Setup

Create Your User Model

public class ApplicationUser : IdentityUser
{
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
    public DateTime CreatedAt { get; set; }
    public DateTime? LastLoginAt { get; set; }
    public string RefreshToken { get; set; } = string.Empty;
    public DateTime RefreshTokenExpiryTime { get; set; }
    public string PictureUrl { get; set; } = string.Empty;
}

Configure Services in Program.cs

using The.Jwt.Auth.Endpoints.Extensions;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

// Add Entity Framework
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

// Configure ASP.NET Core Identity
builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Password.RequireDigit = true;
    options.Password.RequiredLength = 8;
    options.Password.RequireNonAlphanumeric = false;
    options.Password.RequireUppercase = true;
    options.Password.RequireLowercase = false;
    
    options.User.RequireUniqueEmail = true;
    
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.Lockout.AllowedForNewUsers = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

// Required service implementations
builder.Services.AddScoped<IRefreshTokenRepository, RefreshTokenRepository>();
builder.Services.AddScoped<IIdentityUserFactory<ApplicationUser>, SimpleUserFactory>();
builder.Services.AddScoped<IEmailSender<ApplicationUser>, EmailSender>();
builder.Services.AddScoped<IWelcomeActionService, YourWelcomeActionService>();

// Configure JWT Authentication
builder.Services.AddJwtAuthEndpoints<ApplicationUser>(options =>
{
    // JWT Settings
    options.JwtSettings.Secret = "your-super-secret-key-that-should-be-at-least-32-characters-long";
    options.JwtSettings.Issuer = "https://yourapp.com";
    options.JwtSettings.Audience = "YourApp";
    options.JwtSettings.TokenLifeSpanInMinutes = 60;
    options.JwtSettings.RefreshTokenLifeSpanInMinutes = 1440; // 24 hours
    
    // JWT Bearer Token Validation
    options.JwtAuthSchemeOptions.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = "https://yourapp.com",
        ValidAudience = "YourApp",
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your-super-secret-key-that-should-be-at-least-32-characters-long"))
    };
    
    // Optional: Google Firebase Auth
    options.GoogleFirebaseAuthOptions = new AppOptions()
    {
        Credential = GoogleCredential.FromFile("FirebaseServiceAccountFile.json")
    };
});

var app = builder.Build();

// Configure pipeline
app.UseAuthentication();
app.UseAuthorization();

// Map JWT authentication endpoints
app.MapJwtAuthEndpoints<ApplicationUser>();

app.Run();

3. Required Implementations

User Factory

public class SimpleUserFactory : IIdentityUserFactory<ApplicationUser>
{
    public ApplicationUser CreateUser(string firstName, string lastName, string email, string? picture = null)
    {
        return new ApplicationUser
        {
            UserName = email,
            Email = email,
            FirstName = firstName,
            LastName = lastName,
            CreatedAt = DateTime.UtcNow,
            PictureUrl = picture ?? string.Empty
        };
    }
}

Refresh Token Repository

Here's a sample implementation, but you could do what ever you want, as long as it stores the token in a database.

public class RefreshTokenRepository : IRefreshTokenRepository
{
    private readonly ApplicationDbContext _applicationDbContext;

    public RefreshTokenRepository(ApplicationDbContext applicationDbContext)
    {
        _applicationDbContext = applicationDbContext;
    }

    public async Task<bool> AddOrUpdateRefreshToken(string userId, string refreshToken, DateTime expiryTime)
    {
        var user = await _applicationDbContext.Users.FirstOrDefaultAsync(u => u.Id == userId);
        if (user == null)
            return false;

        user.RefreshToken = refreshToken;
        user.RefreshTokenExpiryTime = expiryTime;
        
        await _applicationDbContext.SaveChangesAsync();
        return true;
    }

    public async Task<bool> DeleteRefreshToken(string userId, string refreshToken)
    {
        var user = await _applicationDbContext.Users.FirstOrDefaultAsync(u => u.Id == userId && u.RefreshToken == refreshToken);
        if (user == null)
            return false;

        user.RefreshToken = null;
        user.RefreshTokenExpiryTime = DateTime.MinValue;
        
        await _applicationDbContext.SaveChangesAsync();
        return true;
    }

    public async Task<(string refreshToken, DateTime expiryTime)> GetRefreshToken(string userId)
    {
        var user = await _applicationDbContext.Users.FirstOrDefaultAsync(u => u.Id == userId);
        if (user == null || string.IsNullOrEmpty(user.RefreshToken))
            return (null!, DateTime.MinValue);

        return (user.RefreshToken, user.RefreshTokenExpiryTime);
    }

Email Sender

public class EmailSender : IEmailSender<ApplicationUser>
{
    //Your implementation...
}

Welcome Action Service

The IWelcomeActionService is required and will be called automatically after a user account is successfully created (both during registration and Google social authentication).

public class YourWelcomeActionService : IWelcomeActionService
{
    private readonly ILogger<YourWelcomeActionService> _logger;
    private readonly IEmailService _emailService; // Your email service

    public YourWelcomeActionService(
        ILogger<YourWelcomeActionService> logger,
        IEmailService emailService)
    {
        _logger = logger;
        _emailService = emailService;
    }

    public async Task PerformWelcomeActionsAsync(string userId, string userEmail, string username)
    {
        _logger.LogInformation("Performing welcome actions for user {UserId}", userId);

        // Send welcome email
        await _emailService.SendWelcomeEmailAsync(userEmail, username);

        // Create default user data, initialize preferences, etc.
        // Add any other welcome actions your application requires

        _logger.LogInformation("Welcome actions completed for user {UserId}", userId);
    }
}

Note: This service is called after:

  • New user registration via /api/auth/register
  • New user creation via Google authentication at /api/auth/social/google

It is not called when existing users log in.

Example Usage

Register User

POST /api/auth/register
Content-Type: application/json

{
  "firstName": "John",
  "lastName": "Doe",
  "email": "john.doe@example.com",
  "password": "SecurePassword123"
}

Login

POST /api/auth/login
Content-Type: application/json

{
  "email": "john.doe@example.com",
  "password": "SecurePassword123"
}

Refresh Token

POST /api/auth/refresh
Content-Type: application/json

{
  "accessToken": "your-access-token",
  "refreshToken": "your-refresh-token"
}

Forgot Password

POST /api/auth/forgotPassword
Content-Type: application/json

{
  "email": "john.doe@example.com"
}

Reset Password

POST /api/auth/resetPassword
Content-Type: application/json

{
  "email": "john.doe@example.com",
  "token": "reset-token-from-email",
  "newPassword": "NewSecurePassword123"
}

Google Social Authentication

To enable Google authentication through Firebase:

1. Configure Firebase

  1. Create a Firebase project in the Firebase Console
  2. Enable Authentication and configure Google as a sign-in provider
  3. Download the Service Account Key JSON file
  4. Place the file in your project root and set its Build Action to Content and Copy Always

2. Configure in Code

builder.Services.AddJwtAuthEndpoints<ApplicationUser>(options =>
{
    // ... other configurations
    
    options.GoogleFirebaseAuthOptions = new AppOptions()
    {
        Credential = GoogleCredential.FromFile("FirebaseServiceAccountFile.json")
    };
});

3. Usage

POST /api/auth/social/google
Content-Type: application/json

{
  "idToken": "firebase-id-token-from-client"
}

Configuration Options

JWT Settings

public class JwtSettings
{
    public string Secret { get; set; } = string.Empty;
    public string Issuer { get; set; } = string.Empty;
    public string Audience { get; set; } = string.Empty;
    public int TokenLifeSpanInMinutes { get; set; } = 60;
    public int RefreshTokenLifeSpanInMinutes { get; set; } = 1440;
}

Main Configuration

public class JwtAuthEndpointsConfigOptions
{
    public JwtSettings JwtSettings { get; set; } = new();
    public JwtBearerOptions JwtAuthSchemeOptions { get; set; } = new();
    public AppOptions? GoogleFirebaseAuthOptions { get; set; }
}

Security Features

  • JWT Token Validation: Comprehensive token validation with configurable parameters
  • Refresh Token Rotation: Secure refresh token implementation
  • Email Confirmation: Required email verification for new accounts
  • Password Reset: Secure password reset with time-limited tokens
  • Input Validation: Comprehensive validation using Data Annotations
  • Error Handling: Consistent error responses that don't leak sensitive information
  • Account Lockout: Configurable account lockout after failed attempts

Testing

The library includes comprehensive integration tests. To run them:

dotnet test

Advanced Usage

Custom User Factory

Implement IIdentityUserFactory<TUser> to control user creation:

public class CustomUserFactory : IIdentityUserFactory<ApplicationUser>
{
    public ApplicationUser CreateUser(string firstName, string lastName, string email, string? picture = null)
    {
        return new ApplicationUser
        {
            UserName = email,
            Email = email,
            FirstName = firstName,
            LastName = lastName,
            CreatedAt = DateTime.UtcNow,
            PictureUrl = picture ?? string.Empty,
            // Add custom logic here
        };
    }
}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License. See the LICENSE file for the full license text.

Support

For issues, questions, or feature requests, please create an issue in the GitHub repository.

About

A package that easily adds JWT and social auth + endpoints to your ASP.net core project with minimal efforts on your side.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages