diff --git a/PropelAuth.Tests/PropelAuthOptionsTests.cs b/PropelAuth.Tests/PropelAuthOptionsTests.cs
deleted file mode 100644
index 7bac925..0000000
--- a/PropelAuth.Tests/PropelAuthOptionsTests.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using PropelAuth.Models;
-using Xunit;
-
-namespace PropelAuth.Tests
-{
- public class PropelAuthOptionsTests
- {
- [Fact]
- public void Constructor_ShouldInitializeProperties()
- {
- // Arrange
- string authUrl = "https://auth.example.com";
- string apiKey = "api_12345";
- string publicKey = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...";
-
- // Act
- var options = new PropelAuthOptions(authUrl, apiKey, publicKey);
-
- // Assert
- Assert.Equal(authUrl, options.AuthUrl);
- Assert.Equal(apiKey, options.ApiKey);
- Assert.Equal(publicKey, options.PublicKey);
- }
-
- [Fact]
- public void Constructor_ShouldAcceptNullPublicKey()
- {
- // Arrange
- string authUrl = "https://auth.example.com";
- string apiKey = "api_12345";
-
- // Act
- var options = new PropelAuthOptions(authUrl, apiKey);
-
- // Assert
- Assert.Equal(authUrl, options.AuthUrl);
- Assert.Equal(apiKey, options.ApiKey);
- Assert.Null(options.PublicKey);
- }
- }
-}
\ No newline at end of file
diff --git a/PropelAuth/PropelAuth.csproj b/PropelAuth/PropelAuth.csproj
index 1972bf5..bd70dda 100644
--- a/PropelAuth/PropelAuth.csproj
+++ b/PropelAuth/PropelAuth.csproj
@@ -7,7 +7,7 @@
PropelAuth
- 0.1.0
+ 0.2.0
PropelAuth
PropelAuth
Official .NET SDK for PropelAuth authentication and authorization
@@ -33,10 +33,7 @@
-
-
-
diff --git a/PropelAuth/PropelAuthExtensions.cs b/PropelAuth/PropelAuthExtensions.cs
deleted file mode 100644
index 1850fb4..0000000
--- a/PropelAuth/PropelAuthExtensions.cs
+++ /dev/null
@@ -1,216 +0,0 @@
-using System.IdentityModel.Tokens.Jwt;
-using System.Security.Cryptography;
-using Microsoft.AspNetCore.Authentication.Cookies;
-using Microsoft.AspNetCore.Authentication.JwtBearer;
-using Microsoft.AspNetCore.Authentication.OAuth;
-using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.IdentityModel.Tokens;
-using Newtonsoft.Json.Linq;
-using PropelAuth.Models;
-
-namespace PropelAuth
-{
- ///
- /// Extension methods for configuring PropelAuth authentication in an ASP.NET Core application.
- ///
- public static class PropelAuthExtensions
- {
- ///
- /// Adds PropelAuth authentication to the service collection.
- ///
- /// The service collection to add authentication to.
- /// The PropelAuth configuration options.
- /// The service collection for chaining.
- /// Thrown when the API key is invalid or the verifier key cannot be retrieved.
- public static async Task AddPropelAuthAsync(this IServiceCollection services,
- PropelAuthOptions options)
- {
- // Get the public key either from options or from the PropelAuth API
- string publicKey = await GetPublicKeyAsync(options);
-
- // Configure RSA with the public key
- var rsa = ConfigureRsaWithPublicKey(publicKey);
-
- // Add authentication with JWT bearer
- ConfigureAuthentication(services, options, rsa);
-
- return services;
- }
-
- #region Private Helper Methods
-
- ///
- /// Gets the public key either from options or from the PropelAuth API.
- ///
- /// The PropelAuth configuration options.
- /// The public key in PEM format.
- private static async Task GetPublicKeyAsync(PropelAuthOptions options)
- {
- if (!string.IsNullOrEmpty(options.PublicKey))
- {
- return options.PublicKey;
- }
-
- return await GetVerifierKeyPemAsync(options.AuthUrl, options.ApiKey);
- }
-
- ///
- /// Configures RSA with the provided public key.
- ///
- /// The public key in PEM format.
- /// An initialized RSA instance.
- private static RSA ConfigureRsaWithPublicKey(string publicKey)
- {
- var rsa = RSA.Create();
- rsa.ImportFromPem(publicKey);
- return rsa;
- }
-
- ///
- /// Configures authentication with JWT bearer.
- ///
- /// The service collection to add authentication to.
- /// The PropelAuth configuration options.
- /// The RSA instance configured with the public key.
- private static void ConfigureAuthentication(IServiceCollection services, PropelAuthOptions options, RSA rsa)
- {
- var authBuilder = services.AddAuthentication(authOptions =>
- {
- if (options.OAuthOptions is {AllowBearerTokenAuth: true})
- {
- authOptions.DefaultAuthenticateScheme = "OAuthOrBearer";
- authOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
- authOptions.DefaultChallengeScheme = "OAuthOrBearer";
- }
- else if (options.OAuthOptions != null)
- {
- authOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
- authOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
- authOptions.DefaultChallengeScheme = "OAuth";
- }
- else
- {
- authOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
- authOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
- }
- });
-
- if (options.OAuthOptions is {AllowBearerTokenAuth: true})
- {
- authBuilder.AddPolicyScheme("OAuthOrBearer", "OAuth or Bearer", policyOptions =>
- {
- policyOptions.ForwardDefaultSelector = context =>
- {
- if (context.Request.Headers.ContainsKey("Authorization"))
- {
- return JwtBearerDefaults.AuthenticationScheme;
- }
-
- return "OAuth";
- };
- });
- }
-
-
- if (options.OAuthOptions == null || options.OAuthOptions.AllowBearerTokenAuth == true)
- {
- authBuilder.AddJwtBearer(jwtOptions =>
- {
- jwtOptions.TokenValidationParameters = new TokenValidationParameters
- {
- ValidateAudience = false,
- ValidAlgorithms = new List() {"RS256"},
- ValidIssuer = options.AuthUrl,
- IssuerSigningKey = new RsaSecurityKey(rsa),
- ValidateLifetime = true,
- };
- });
- }
-
- if (options.OAuthOptions != null)
- {
- authBuilder
- .AddCookie(cookieOptions =>
- {
- cookieOptions.Cookie.SameSite = SameSiteMode.Lax;
- cookieOptions.Cookie.HttpOnly = true;
- cookieOptions.Cookie.SecurePolicy = CookieSecurePolicy.Always;
- cookieOptions.SlidingExpiration = true;
- })
- .AddOAuth("OAuth", configOptions =>
- {
- configOptions.AuthorizationEndpoint = $"{options.AuthUrl}/propelauth/oauth/authorize";
- configOptions.TokenEndpoint = $"{options.AuthUrl}/propelauth/oauth/token";
- configOptions.UserInformationEndpoint = $"{options.AuthUrl}/propelauth/oauth/userinfo";
- configOptions.ClientId = options.OAuthOptions.ClientId;
- configOptions.ClientSecret = options.OAuthOptions.ClientSecret;
- configOptions.CallbackPath = options.OAuthOptions.CallbackPath;
- configOptions.SaveTokens = true;
- configOptions.Events = new OAuthEvents
- {
- OnCreatingTicket = context =>
- {
- var token = context.AccessToken;
- var handler = new JwtSecurityTokenHandler();
- var jwt = handler.ReadJwtToken(token);
- foreach (var claim in jwt.Claims)
- {
- context.Identity?.AddClaim(claim);
- }
-
- return Task.CompletedTask;
- }
- };
- });
- }
-
- services.AddAuthorization();
- }
-
- ///
- /// Gets the verifier key in PEM format from the PropelAuth API.
- ///
- /// The PropelAuth issuer URL.
- /// The PropelAuth API key.
- /// The verifier key in PEM format.
- /// Thrown when the API key is invalid or the verifier key cannot be retrieved.
- private static async Task GetVerifierKeyPemAsync(string issuer, string apiKey)
- {
- using (var client = new HttpClient())
- {
- client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
- var response = await client.GetAsync($"{issuer}/api/v1/token_verification_metadata");
-
- if (response.IsSuccessStatusCode)
- {
- return await ParseVerifierKeyFromResponse(response);
- }
-
- throw new Exception("Error in initializing library, this is likely due to an incorrect API Key");
- }
- }
-
- ///
- /// Parses the verifier key from the API response.
- ///
- /// The HTTP response from the PropelAuth API.
- /// The verifier key in PEM format.
- /// Thrown when the verifier key is missing in the response.
- private static async Task ParseVerifierKeyFromResponse(HttpResponseMessage response)
- {
- var content = await response.Content.ReadAsStringAsync();
- var json = JObject.Parse(content);
- var verifierKeyPem = json["verifier_key_pem"]?.ToString();
-
- if (verifierKeyPem == null)
- {
- throw new Exception("verifier_key_pem is missing in the response");
- }
-
- return verifierKeyPem;
- }
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/PropelAuth/PropelAuthOptions.cs b/PropelAuth/PropelAuthOptions.cs
deleted file mode 100644
index 9edc63b..0000000
--- a/PropelAuth/PropelAuthOptions.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-namespace PropelAuth.Models
-{
- ///
- /// Configuration options for PropelAuth authentication service.
- ///
- public class PropelAuthOptions
- {
- #region Properties
-
- ///
- /// Gets the public key used for token verification.
- ///
- ///
- /// This key is optional, if unspecified, we will fetch the public key from the authentication service.
- ///
- public string? PublicKey { get; }
-
- ///
- /// Gets the base URL for the PropelAuth authentication service.
- ///
- public string AuthUrl { get; }
-
- ///
- /// Gets the API key used for authenticating requests to PropelAuth.
- ///
- public string ApiKey { get; }
-
- ///
- /// If you are using PropelAuth's OAuth feature, you can specify the OAuth options here.
- ///
- public OAuthOptions? OAuthOptions { get; }
-
- #endregion
-
- #region Constructors
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The base URL for the PropelAuth authentication service.
- /// The API key used for authenticating requests to PropelAuth.
- /// Optional. The public key used for token verification.
- /// Optional. The OAuth options if you are using PropelAuth's OAuth feature.
- public PropelAuthOptions(string authUrl, string apiKey, string? publicKey = null,
- OAuthOptions? oAuthOptions = null)
- {
- AuthUrl = authUrl;
- ApiKey = apiKey;
- PublicKey = publicKey;
- OAuthOptions = oAuthOptions;
- }
-
- #endregion
- }
-
- public class OAuthOptions
- {
- #region Properties
-
- ///
- /// The client ID for the OAuth application.
- ///
- public string ClientId { get; }
-
- ///
- /// The client secret for the OAuth application.
- ///
- public string ClientSecret { get; }
-
- ///
- /// The callback path for the OAuth application. Defaults to "/callback"
- ///
- public string? CallbackPath { get; }
-
- ///
- /// Whether to allow requests via an authorization header `Bearer {TOKEN}`. Default false.
- ///
- public bool? AllowBearerTokenAuth { get; }
-
- #endregion
-
- #region Constructor
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The client ID for the OAuth application.
- /// The client secret for the OAuth application.
- /// Optional. The callback path for the OAuth application. Defaults to "/callback"
- /// Optional. Whether to allow requests via an authorization header `Bearer {TOKEN}`. Default false.
- public OAuthOptions(string clientId, string clientSecret, string? callbackPath = "/callback", bool? allowBearerTokenAuth = false)
- {
- ClientId = clientId;
- ClientSecret = clientSecret;
- CallbackPath = callbackPath;
- AllowBearerTokenAuth = allowBearerTokenAuth;
- }
-
- #endregion
-
- }
-}
\ No newline at end of file
diff --git a/PropelAuth/User.cs b/PropelAuth/User.cs
index 3932b03..41934c2 100644
--- a/PropelAuth/User.cs
+++ b/PropelAuth/User.cs
@@ -10,15 +10,41 @@ public class User
{
#region Properties
- // Public properties
+ ///
+ /// The unique identifier for the user.
+ ///
public string UserId { get; }
+ ///
+ /// The email address of the user.
+ ///
public string Email { get; }
+ ///
+ /// The user's first name
+ ///
public string? FirstName { get; }
+ ///
+ /// The user's last name
+ ///
public string? LastName { get; }
+ ///
+ /// The user's username
+ ///
public string? Username { get; }
+ ///
+ /// The user's legacy user ID. This is only set if you migrated from an external source
+ ///
public string? LegacyUserId { get; }
+ ///
+ /// The method the user used to log in. Returns an instance of that describes the login method.
+ ///
public LoginMethod LoginMethod { get; }
+ ///
+ /// If the user is being impersonated, this is the ID of the impersonator.
+ ///
public string? ImpersonatorUserId { get; }
+ ///
+ /// Additional properties set on the user.
+ ///
public Dictionary? Properties { get; }
// Private properties