Authorizer.DotNet 1.0.4

dotnet add package Authorizer.DotNet --version 1.0.4
                    
NuGet\Install-Package Authorizer.DotNet -Version 1.0.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Authorizer.DotNet" Version="1.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Authorizer.DotNet" Version="1.0.4" />
                    
Directory.Packages.props
<PackageReference Include="Authorizer.DotNet" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Authorizer.DotNet --version 1.0.4
                    
#r "nuget: Authorizer.DotNet, 1.0.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Authorizer.DotNet@1.0.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Authorizer.DotNet&version=1.0.4
                    
Install as a Cake Addin
#tool nuget:?package=Authorizer.DotNet&version=1.0.4
                    
Install as a Cake Tool

Authorizer.DotNet

NuGet Version License .NET

Official .NET SDK for Authorizer.dev - a powerful authentication and authorization service. This SDK provides comprehensive authentication features for .NET applications including ASP.NET Core, Blazor Server/WebAssembly, worker services, and console applications.

Features

  • ๐Ÿ” Complete Authentication Flow: Login, signup, password reset, email verification
  • ๐ŸŽฏ Multi-Target Support: .NET 6.0, 7.0, and 8.0
  • ๐Ÿ—๏ธ Multiple Project Types: ASP.NET Core, Blazor Server, Console, Worker Services
  • ๐Ÿ”„ OAuth 2.0 & OpenID Connect: Full OAuth/OIDC support with PKCE
  • ๐Ÿ›ก๏ธ JWT Token Management: Validation, refresh, and secure storage
  • ๐Ÿ“ฑ Multi-Factor Authentication: Support for MFA flows
  • ๐ŸŒ Social Login: Integration with social providers
  • ๐Ÿ”ง Dependency Injection: Native .NET DI container support
  • ๐Ÿ“Š Structured Logging: Built-in logging with configurable levels
  • โšก High Performance: Optimized HTTP client with connection pooling
  • ๐ŸŒ Cross-Domain Support: Clear error messages and explicit token-based validation
  • ๐Ÿงช Production Ready: Comprehensive error handling and resilience

Installation

Install the NuGet package:

dotnet add package Authorizer.DotNet

Or via Package Manager Console:

Install-Package Authorizer.DotNet

Quick Start

1. ASP.NET Core API

Add Authorizer to your Program.cs:

using Authorizer.DotNet.Extensions;

var builder = WebApplication.CreateBuilder(args);

// Add Authorizer services
builder.Services.AddAuthorizer(builder.Configuration, "Authorizer");

// Add authentication & authorization
builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
        options.Authority = builder.Configuration["Authorizer:AuthorizerUrl"];
        options.RequireHttpsMetadata = false; // Only for development
    });

builder.Services.AddAuthorization();

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();
app.Run();

Configure in appsettings.json:

{
  "Authorizer": {
    "AuthorizerUrl": "https://your-authorizer-instance.com",
    "RedirectUrl": "https://your-app.com/auth/callback",
    "ClientId": "your-client-id",
    "HttpTimeout": "00:00:30"
  }
}

Use in your controllers:

[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
    private readonly IAuthorizerClient _authorizerClient;

    public AuthController(IAuthorizerClient authorizerClient)
    {
        _authorizerClient = authorizerClient;
    }

    [HttpPost("login")]
    public async Task<IActionResult> Login([FromBody] LoginRequest request)
    {
        var response = await _authorizerClient.LoginAsync(request);
        
        if (response.IsSuccess)
        {
            return Ok(response.Data);
        }

        return BadRequest(new { errors = response.Errors });
    }
}

2. Blazor Server

Configure in Program.cs:

using Microsoft.AspNetCore.Authentication.Cookies;
using Authorizer.DotNet.Extensions;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();

// Add Authorizer
builder.Services.AddAuthorizer(builder.Configuration, "Authorizer");

// Add cookie authentication
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.LoginPath = "/login";
        options.LogoutPath = "/logout";
    });

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

app.MapRazorPages();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

Create a login component:

@page "/login"
@inject IAuthorizerClient AuthorizerClient
@inject NavigationManager Navigation

<EditForm Model="@loginModel" OnValidSubmit="@HandleLogin">
    <div>
        <label>Email:</label>
        <InputText @bind-Value="loginModel.Email" />
    </div>
    <div>
        <label>Password:</label>
        <InputText type="password" @bind-Value="loginModel.Password" />
    </div>
    <button type="submit">Login</button>
</EditForm>

@code {
    private LoginRequest loginModel = new();

    private async Task HandleLogin()
    {
        var response = await AuthorizerClient.LoginAsync(loginModel);
        
        if (response.IsSuccess)
        {
            // Handle successful login
            Navigation.NavigateTo("/");
        }
    }
}

3. Console Application

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Authorizer.DotNet.Extensions;
using Authorizer.DotNet.Models.Requests;

var builder = Host.CreateApplicationBuilder(args);

builder.Services.AddAuthorizer(options =>
{
    options.AuthorizerUrl = "https://your-authorizer-instance.com";
    options.RedirectUrl = "http://localhost:3000/callback";
    options.ClientId = "your-client-id";
});

var host = builder.Build();
var authorizerClient = host.Services.GetRequiredService<IAuthorizerClient>();

// Login example
var loginRequest = new LoginRequest
{
    Email = "user@example.com",
    Password = "password123"
};

var response = await authorizerClient.LoginAsync(loginRequest);

if (response.IsSuccess)
{
    Console.WriteLine($"Login successful! Access token: {response.Data?.AccessToken}");
    
    // Get user profile
    var profile = await authorizerClient.GetProfileAsync(response.Data!.AccessToken!);
    if (profile.IsSuccess)
    {
        Console.WriteLine($"Welcome, {profile.Data?.Email}!");
    }
}
else
{
    Console.WriteLine($"Login failed: {response.FirstErrorMessage}");
}

Configuration Options

Basic Configuration

services.AddAuthorizer(options =>
{
    options.AuthorizerUrl = "https://your-authorizer-instance.com";
    options.RedirectUrl = "https://your-app.com/auth/callback";
    options.ClientId = "your-client-id";
    options.HttpTimeout = TimeSpan.FromSeconds(30);
    options.ApiKey = "your-api-key"; // Optional for server-to-server
});

Advanced Configuration

services.AddAuthorizer(
    options =>
    {
        options.AuthorizerUrl = "https://your-authorizer-instance.com";
        options.RedirectUrl = "https://your-app.com/auth/callback";
        options.ClientId = "your-client-id";
        options.UseSecureCookies = true;
        options.CookieDomain = ".your-domain.com";
        options.ExtraHeaders = new Dictionary<string, string>
        {
            ["X-Custom-Header"] = "custom-value"
        };
    },
    httpClient =>
    {
        // Configure HttpClient
        httpClient.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
    });

Cross-Domain Authentication

For scenarios where your Authorizer instance and application are on different subdomains:

services.AddAuthorizer(options =>
{
    options.AuthorizerUrl = "https://auth.example.com";
    options.RedirectUrl = "https://app.example.com/auth/callback";
    options.ClientId = "your-client-id";
    
    // Cross-domain configuration
    options.UseCookies = true;                    // Enable cookie handling
    options.UseCredentials = true;                // Include credentials in CORS
    options.CookieDomain = ".example.com";        // Cross-domain cookie sharing
});

The simplified SDK approach provides:

  1. Clear, actionable error messages for authentication issues
  2. Explicit token-based session validation via ValidateSessionWithTokenAsync
  3. Developer control over authentication flow
  4. Transparent error handling without hidden automatic retries

Configuration from appsettings.json

{
  "Authorizer": {
    "AuthorizerUrl": "https://your-authorizer-instance.com",
    "RedirectUrl": "https://your-app.com/auth/callback",
    "ClientId": "your-client-id",
    "HttpTimeout": "00:00:30",
    "ApiKey": "your-api-key",
    "UseSecureCookies": true,
    "CookieDomain": ".your-domain.com",
    "UseCookies": true,
    "UseCredentials": true,
    "ExtraHeaders": {
      "X-Custom-Header": "custom-value"
    }
  }
}

API Reference

Authentication Methods

LoginAsync
Task<AuthorizerResponse<LoginResponse>> LoginAsync(LoginRequest request, CancellationToken cancellationToken = default)

Authenticates a user with email and password.

SignupAsync
Task<AuthorizerResponse<SignupResponse>> SignupAsync(SignupRequest request, CancellationToken cancellationToken = default)

Registers a new user account.

AuthorizeAsync
Task<AuthorizerResponse<AuthorizeResponse>> AuthorizeAsync(AuthorizeRequest request, CancellationToken cancellationToken = default)

Initiates OAuth authorization flow.

GetTokenAsync
Task<AuthorizerResponse<TokenResponse>> GetTokenAsync(GetTokenRequest request, CancellationToken cancellationToken = default)

Exchanges authorization code for access token.

LogoutAsync
Task<AuthorizerResponse<bool>> LogoutAsync(string? sessionToken = null, CancellationToken cancellationToken = default)

Logs out the current user session.

User Management

GetProfileAsync
Task<AuthorizerResponse<UserProfile>> GetProfileAsync(string accessToken, CancellationToken cancellationToken = default)

Retrieves the current user's profile information.

GetSessionAsync
Task<AuthorizerResponse<SessionInfo>> GetSessionAsync(string? sessionToken = null, CancellationToken cancellationToken = default)

Retrieves current session information using cookies.

ValidateSessionWithTokenAsync
Task<AuthorizerResponse<SessionInfo>> ValidateSessionWithTokenAsync(string accessToken, CancellationToken cancellationToken = default)

Validates a session using a provided access token instead of cookies. Useful for cross-domain scenarios or when you prefer explicit token-based authentication.

Password Management

ForgotPasswordAsync
Task<AuthorizerResponse<bool>> ForgotPasswordAsync(string email, CancellationToken cancellationToken = default)

Initiates password reset flow.

ResetPasswordAsync
Task<AuthorizerResponse<bool>> ResetPasswordAsync(ResetPasswordRequest request, CancellationToken cancellationToken = default)

Resets user password using reset token.

ChangePasswordAsync
Task<AuthorizerResponse<bool>> ChangePasswordAsync(ChangePasswordRequest request, CancellationToken cancellationToken = default)

Changes user password (requires current password).

Verification

VerifyEmailAsync
Task<AuthorizerResponse<bool>> VerifyEmailAsync(VerifyEmailRequest request, CancellationToken cancellationToken = default)

Verifies user's email address.

ValidateJwtAsync
Task<AuthorizerResponse<UserProfile>> ValidateJwtAsync(string token, CancellationToken cancellationToken = default)

Validates a JWT token and returns user information.

Metadata

GetMetaAsync
Task<AuthorizerResponse<MetaInfo>> GetMetaAsync(CancellationToken cancellationToken = default)

Retrieves metadata about the Authorizer instance.

Authentication Flows

OAuth 2.0 Authorization Code Flow with PKCE

// 1. Start authorization
var authorizeRequest = new AuthorizeRequest
{
    ResponseType = "code",
    ClientId = "your-client-id",
    RedirectUri = "https://your-app.com/callback",
    Scope = "openid email profile",
    State = "random-state-value",
    CodeChallenge = "generated-code-challenge",
    CodeChallengeMethod = "S256"
};

var authResponse = await client.AuthorizeAsync(authorizeRequest);

// 2. User is redirected to authorization server
// 3. After user consent, exchange code for tokens
var tokenRequest = new GetTokenRequest
{
    GrantType = "authorization_code",
    Code = "received-authorization-code",
    CodeVerifier = "original-code-verifier",
    ClientId = "your-client-id",
    RedirectUri = "https://your-app.com/callback"
};

var tokenResponse = await client.GetTokenAsync(tokenRequest);

Refresh Token Flow

var refreshRequest = new GetTokenRequest
{
    GrantType = "refresh_token",
    RefreshToken = "your-refresh-token",
    ClientId = "your-client-id"
};

var newTokens = await client.GetTokenAsync(refreshRequest);

Error Handling

The SDK provides comprehensive error handling with structured error responses:

var response = await client.LoginAsync(request);

if (response.IsSuccess)
{
    // Handle success
    var user = response.Data?.User;
    var accessToken = response.Data?.AccessToken;
}
else
{
    // Handle errors
    foreach (var error in response.Errors ?? Array.Empty<AuthorizerError>())
    {
        Console.WriteLine($"Error: {error.Message} (Code: {error.Code})");
    }
    
    // Or get the first error message
    var firstError = response.FirstErrorMessage;
}

Exception Handling

try
{
    var response = await client.LoginAsync(request);
}
catch (AuthorizerException ex)
{
    // SDK-specific errors
    Console.WriteLine($"Authorizer error: {ex.Message}");
    Console.WriteLine($"HTTP Status: {ex.StatusCode}");
    
    if (ex.Errors != null)
    {
        foreach (var error in ex.Errors)
        {
            Console.WriteLine($"- {error.Message}");
        }
    }
}
catch (HttpRequestException ex)
{
    // Network errors
    Console.WriteLine($"Network error: {ex.Message}");
}
catch (TaskCanceledException ex)
{
    // Timeout errors
    Console.WriteLine($"Request timeout: {ex.Message}");
}

Advanced Usage

Custom HTTP Client Configuration

services.AddAuthorizer(
    options => { /* configure options */ },
    (serviceProvider, httpClient) =>
    {
        // Access to IServiceProvider for advanced scenarios
        var logger = serviceProvider.GetService<ILogger<Program>>();
        
        httpClient.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
        httpClient.Timeout = TimeSpan.FromSeconds(60);
    });

Using with Polly for Resilience

services.AddAuthorizer(options => { /* configure */ })
    .AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(10))
    .AddPolicyHandler(Policy
        .Handle<HttpRequestException>()
        .WaitAndRetryAsync(3, retryAttempt => 
            TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))));

Validation Attributes

Request models include built-in validation:

public class LoginRequest
{
    [Required]
    [EmailAddress]
    public string Email { get; set; } = string.Empty;

    [Required]
    public string Password { get; set; } = string.Empty;
}

Use with ASP.NET Core model validation:

[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginRequest request)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    var response = await _authorizerClient.LoginAsync(request);
    // ... handle response
}

Samples

The repository includes comprehensive samples:

  • ASP.NET Core API: JWT authentication, protected endpoints, Swagger integration
  • Blazor Server: Cookie-based authentication, login/logout components, protected pages
  • Console Application: Complete authentication flow demonstration, error handling

Run the samples:

# ASP.NET Core API
cd samples/Authorizer.Sample.AspNetCore
dotnet run

# Blazor Server
cd samples/Authorizer.Sample.BlazorServer
dotnet run

# Console
cd samples/Authorizer.Sample.Console
dotnet run

Logging

The SDK provides structured logging for debugging and monitoring:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Authorizer.DotNet": "Debug"
    }
  }
}

Log events include:

  • HTTP requests/responses
  • Authentication flow steps
  • Error details
  • Performance metrics

Testing

The Authorizer.DotNet SDK includes a comprehensive test suite with 84 unit tests covering all public APIs and core functionality. All tests include complete XML documentation for enhanced maintainability.

Test Framework & Tools

  • xUnit: Primary testing framework for .NET
  • Moq: Mocking framework for creating test doubles
  • Microsoft.NET.Test.Sdk: Test platform and runners
  • Coverlet: Code coverage collection

Test Coverage

โœ… Model Tests (100% Coverage)
  • AuthorizerResponse<T>: Generic response wrapper validation

    • Success/failure response creation
    • Error handling and validation
    • Property validation and serialization
  • LoginRequest: Input validation and data annotations

    • Email format validation ([EmailAddress])
    • Required field validation ([Required])
    • Optional field handling (Scope, State, Roles)
  • SignupRequest: Complete registration model validation

    • All 16 properties with proper validation
    • Required vs optional field handling
    • Complex object validation (roles, app data)
โœ… Client Tests (Core Functionality)
  • AuthorizerClient: All 12 public methods tested
    • Constructor validation and dependency injection
    • Authentication methods (Login, Signup, OAuth flows)
    • User management (GetProfile, GetSession, Logout)
    • Password management (Forgot, Reset, Change)
    • Email verification and JWT validation
    • Error handling and argument validation
โœ… HTTP Client Tests (Integration Layer)
  • AuthorizerHttpClient: Network communication layer
    • GraphQL request handling and response parsing
    • Form data posting for OAuth endpoints
    • Response deserialization and error mapping
    • Exception handling (timeouts, network errors)
    • HTTP status code handling

Running Tests

# Run all tests
dotnet test tests/Authorizer.DotNet.UnitTests/

# Run with detailed output
dotnet test tests/Authorizer.DotNet.UnitTests/ --verbosity normal

# Run with code coverage
dotnet test tests/Authorizer.DotNet.UnitTests/ --collect:"XPlat Code Coverage"

Test Results Summary

  • Unit Tests: 84 tests (100% passing)
  • Integration Tests: 13 comprehensive scenarios (76.9% passing with live API)
  • Test Categories:
    • Unit Tests: Model validation, business logic
    • Integration Tests: HTTP communication, API contracts, real API testing
    • Mocking Tests: Dependency isolation, error scenarios

Unit Testing Examples

Testing Authentication Flow
[Fact]
public async Task LoginAsync_WithValidRequest_ShouldReturnSuccessResponse()
{
    // Arrange
    var mockHttpClient = new Mock<AuthorizerHttpClient>();
    var loginRequest = new LoginRequest 
    { 
        Email = "test@example.com", 
        Password = "password123" 
    };
    
    var expectedResponse = AuthorizerResponse<LoginResponse>.Success(
        new LoginResponse { AccessToken = "test-token" });
    
    mockHttpClient.Setup(x => x.PostGraphQLAsync<LoginResponse>(
        It.IsAny<string>(), It.IsAny<object>(), default))
        .ReturnsAsync(expectedResponse);

    var client = new AuthorizerClient(mockHttpClient.Object, options, logger);

    // Act
    var result = await client.LoginAsync(loginRequest);

    // Assert
    Assert.True(result.IsSuccess);
    Assert.Equal("test-token", result.Data?.AccessToken);
}
Testing Input Validation
[Theory]
[InlineData("invalid-email")]
[InlineData("@example.com")]
[InlineData("test@")]
public void Email_WhenInvalidFormat_ShouldFailValidation(string email)
{
    // Arrange
    var request = new LoginRequest { Email = email, Password = "password123" };
    
    // Act
    var validationResults = ValidateModel(request);
    
    // Assert
    Assert.Contains(validationResults, vr => vr.MemberNames.Contains("Email"));
}
Testing Error Handling
[Fact]
public async Task LoginAsync_WithNullRequest_ShouldThrowArgumentNullException()
{
    // Arrange
    var client = CreateAuthorizerClient();
    
    // Act & Assert
    await Assert.ThrowsAsync<ArgumentNullException>(() => client.LoginAsync(null!));
}

Integration Testing with ASP.NET Core

public class AuthorizerIntegrationTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly WebApplicationFactory<Program> _factory;
    private readonly HttpClient _client;

    public AuthorizerIntegrationTests(WebApplicationFactory<Program> factory)
    {
        _factory = factory;
        _client = _factory.WithWebHostBuilder(builder =>
        {
            builder.ConfigureTestServices(services =>
            {
                services.AddAuthorizer(options =>
                {
                    options.AuthorizerUrl = "https://demo.authorizer.dev";
                    options.RedirectUrl = "https://test.app/callback";
                });
            });
        }).CreateClient();
    }

    [Fact]
    public async Task Login_WithValidCredentials_ReturnsSuccessResponse()
    {
        // Arrange
        var loginRequest = new { email = "test@example.com", password = "password123" };
        var json = JsonSerializer.Serialize(loginRequest);
        var content = new StringContent(json, Encoding.UTF8, "application/json");

        // Act
        var response = await _client.PostAsync("/api/auth/login", content);

        // Assert
        response.EnsureSuccessStatusCode();
        var responseContent = await response.Content.ReadAsStringAsync();
        Assert.Contains("access_token", responseContent);
    }
}

Mock-Free Testing (TestServer)

[Fact]
public async Task AuthorizerClient_RealHttpCalls_WithTestServer()
{
    using var server = new TestServer(new WebHostBuilder()
        .ConfigureServices(services =>
        {
            services.AddAuthorizer(options =>
            {
                options.AuthorizerUrl = "http://localhost";
                options.RedirectUrl = "http://localhost/callback";
            });
        }));

    var client = server.Services.GetRequiredService<IAuthorizerClient>();
    
    // Test actual HTTP behavior without mocking
    var metaResponse = await client.GetMetaAsync();
    
    // Assertions based on actual API behavior
    Assert.NotNull(metaResponse);
}

Test Best Practices Implemented

  1. AAA Pattern: Arrange, Act, Assert structure
  2. Descriptive Names: Clear test method names describing scenarios
  3. Theory Tests: Data-driven tests with [Theory] and [InlineData]
  4. Proper Mocking: Isolated units with controlled dependencies
  5. Edge Case Testing: Null inputs, invalid data, boundary conditions
  6. Async Testing: Proper async/await patterns with CancellationToken
  7. Exception Testing: Verifying proper exception handling
  8. Validation Testing: Model validation and data annotation testing
  9. XML Documentation: Complete documentation for all test methods and classes

Contributing Tests

When contributing to the project:

  1. Write tests first (TDD approach recommended)
  2. Maintain high coverage for new features
  3. Test both success and failure scenarios
  4. Include validation tests for request models
  5. Mock external dependencies appropriately
  6. Use meaningful test data that reflects real-world usage
  7. Add XML documentation to all new test methods and classes

Integration Tests

The SDK includes comprehensive integration tests that verify functionality against real Authorizer instances:

# Run integration tests (uses demo instance by default)
cd tests/Authorizer.DotNet.IntegrationTests/
dotnet test

Configure your instance credentials:

{
  "Authorizer": {
    "AuthorizerUrl": "https://your-authorizer-instance.com",
    "ClientId": "your-client-id",
    "RedirectUrl": "https://your-app.com/auth/callback"
  }
}

Integration test coverage includes:

  • โœ… Meta information retrieval
  • โœ… User signup and login flows
  • โœ… Session management and JWT validation
  • โœ… Profile retrieval and user management
  • โœ… Password reset workflows
  • โœ… OAuth authorization flows
  • โœ… Error handling and edge cases
  • โœ… Rate limiting and network resilience

The integration tests provide a comprehensive validation that the SDK works correctly with real Authorizer instances, ensuring production readiness.

The test suite ensures reliability and prevents regressions as the SDK evolves.

Performance Considerations

  • Connection Pooling: Uses HttpClientFactory for optimal connection reuse
  • JSON Serialization: Optimized with System.Text.Json and UTF-8 byte arrays
  • Memory Allocation: Minimal allocations with object pooling where appropriate
  • Async/Await: Fully asynchronous API with proper ConfigureAwait(false) usage
  • Cancellation Support: All methods support CancellationToken for graceful cancellation

Security Best Practices

  1. Always use HTTPS in production environments
  2. Validate SSL certificates - don't disable certificate validation
  3. Store secrets securely - use Azure Key Vault, AWS Secrets Manager, etc.
  4. Implement proper token storage - use secure HTTP-only cookies or encrypted storage
  5. Handle token refresh - implement automatic token refresh logic
  6. Validate user permissions - always check user roles and permissions
  7. Use PKCE - implement PKCE for OAuth flows in public clients

Migration Guide

From JavaScript SDK

The .NET SDK closely mirrors the JavaScript SDK API:

JavaScript:

const response = await authorizerRef.login({
  email: 'user@example.com',
  password: 'password123'
});

.NET:

var response = await authorizerClient.LoginAsync(new LoginRequest
{
    Email = "user@example.com",
    Password = "password123"
});

Troubleshooting

Common Issues

  1. "AuthorizerOptions.AuthorizerUrl must be configured"

    • Ensure you've configured the AuthorizerUrl in your settings
  2. "HTTP 401 Unauthorized"

    • Check your API key or client credentials
    • Verify the access token is included in requests
  3. "HTTP 404 Not Found"

    • Verify the AuthorizerUrl is correct
    • Check that your Authorizer instance is running
  4. "HTTP 422 Unprocessable Entity" (Cross-Domain Issues)

    • Common in scenarios where auth server and app are on different subdomains
    • Use explicit token validation: await client.ValidateSessionWithTokenAsync(token)
    • Configure cross-domain cookies: options.CookieDomain = ".yourdomain.com"
    • Enable CORS credentials: options.UseCredentials = true
    • Check browser console for CORS errors
  5. SSL/TLS Errors

    • For development, you may need to disable SSL validation
    • In production, ensure valid SSL certificates
  6. Timeout Errors

    • Increase HttpTimeout in configuration
    • Check network connectivity
  7. Cross-Domain Authentication Not Working

    • Ensure CookieDomain starts with a dot (e.g., .example.com)
    • Verify CORS is configured on your Authorizer instance
    • Use explicit token validation: ValidateSessionWithTokenAsync(accessToken)
    • Check error messages for actionable troubleshooting guidance

Enable Debug Logging

{
  "Logging": {
    "LogLevel": {
      "Authorizer.DotNet": "Debug"
    }
  }
}

This will log all HTTP requests/responses for debugging.

Documentation

For comprehensive documentation, see the docs directory:

Contributing

We welcome contributions! Please see our Contributing Guide for details.

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

Support

License

This project is licensed under the MIT License - see the LICENSE file for details.

Changelog

See CHANGELOG.md for a detailed list of changes.


Made with โค๏ธ in London

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.4 10 8/20/2025