changes: Working SSo flow

This commit is contained in:
2025-10-14 21:15:25 -06:00
parent 8f88b8bb6c
commit a1b917f59c
4 changed files with 60 additions and 15 deletions

View File

@@ -82,12 +82,29 @@ public class ExternalAuthenticationManager : DomainService
// 3. Validate JWT token
var claims = await ValidateTokenAsync(provider, idToken);
var sub = claims.FirstOrDefault(c => c.Type == "sub")?.Value;
var email = claims.FirstOrDefault(c => c.Type == "email")?.Value;
// Log all claims for debugging
Logger.Info("Claims received from token:");
foreach (var claim in claims)
{
Logger.Info($" {claim.Type} = {claim.Value}");
}
// Try to find subject identifier (sub, uid, user_id, etc.)
var sub = claims.FirstOrDefault(c => c.Type == "sub")?.Value
?? claims.FirstOrDefault(c => c.Type == "uid")?.Value
?? claims.FirstOrDefault(c => c.Type == "user_id")?.Value
?? claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
// Try to find email using multiple formats
var email = claims.FirstOrDefault(c => c.Type == "email")?.Value
?? claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value
?? claims.FirstOrDefault(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress")?.Value;
if (string.IsNullOrEmpty(sub))
{
throw new UserFriendlyException("Invalid token: 'sub' claim not found");
Logger.Error("Subject claim not found. Available claims: " + string.Join(", ", claims.Select(c => c.Type)));
throw new UserFriendlyException("Invalid token: 'sub' claim not found. Check server logs for details.");
}
// 4. Find or create user
@@ -337,7 +354,23 @@ public class ExternalAuthenticationManager : DomainService
mappedType = claimType;
}
return claims.FirstOrDefault(c => c.Type == mappedType)?.Value;
// Try to find the claim by mapped type or standard type
var value = claims.FirstOrDefault(c => c.Type == mappedType)?.Value;
if (!string.IsNullOrEmpty(value))
{
return value;
}
// Fallback: Try common Microsoft claim type mappings
return claimType switch
{
"email" => claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value,
"name" => claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value,
"given_name" => claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value,
"family_name" => claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value,
"preferred_username" => claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value,
_ => null
};
}
private int GetTokenExpiration(string idToken)

View File

@@ -64,7 +64,7 @@ namespace ASPBaseOIDC.Controllers
/// <summary>
/// Authenticate with external OIDC/OAuth2 provider (Authentik, Keycloak, etc.)
/// Passthrough approach: validates external token and returns it as-is
/// Validates external token and returns backend's own JWT
/// </summary>
[HttpPost]
[AbpAllowAnonymous]
@@ -77,12 +77,26 @@ namespace ASPBaseOIDC.Controllers
AbpSession.TenantId
);
// Return original external token (passthrough approach)
// Create claims identity for the user (same as local login)
var identity = new ClaimsIdentity();
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, result.User.Id.ToString()));
identity.AddClaim(new Claim(ClaimTypes.Name, result.User.UserName));
identity.AddClaim(new Claim(ClaimTypes.Email, result.User.EmailAddress));
// Add tenant claim if applicable
if (result.User.TenantId.HasValue)
{
identity.AddClaim(new Claim(AbpClaimTypes.TenantId, result.User.TenantId.Value.ToString()));
}
// Generate backend's own JWT token
var accessToken = CreateAccessToken(CreateJwtClaims(identity));
return new AuthenticateResultModel
{
AccessToken = result.AccessToken, // Passthrough external token
EncryptedAccessToken = GetEncryptedAccessToken(result.AccessToken),
ExpireInSeconds = result.ExpiresIn,
AccessToken = accessToken, // Backend's own JWT
EncryptedAccessToken = GetEncryptedAccessToken(accessToken),
ExpireInSeconds = (int)_configuration.Expiration.TotalSeconds,
UserId = result.User.Id
};
}

View File

@@ -3,8 +3,7 @@
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:44313/",
"sslPort": 44313
"applicationUrl": "http://localhost:44312/"
}
},
"profiles": {
@@ -18,8 +17,7 @@
"ASPBaseOIDC.Web.Host": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:44313/",
"sslPort": 44313,
"applicationUrl": "http://localhost:44312/",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}

View File

@@ -5,7 +5,7 @@
"App": {
"ServerRootAddress": "https://localhost:44311/",
"ClientRootAddress": "http://localhost:4200/",
"CorsOrigins": "http://localhost:4200,http://localhost:8080,http://localhost:8081,http://localhost:3000"
"CorsOrigins": "http://localhost:4200,http://localhost:8080,http://localhost:8081,http://localhost:3000,http://localhost:3001"
},
"Authentication": {
"JwtBearer": {
@@ -26,7 +26,7 @@
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "https://localhost:44311/"
"Url": "http://localhost:44311/"
}
}
},