refactor: Projektdateien migriert. Cloud-NuGet-Pakete durch lokale NuGet-Projekte ersetzt.

This commit is contained in:
Developer 02
2024-08-01 18:44:39 +02:00
parent 0d82f7af6f
commit 62ddd4873f
206 changed files with 10927 additions and 1 deletions

View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<PackageId>HRD.LDAPService</PackageId>
<Authors>Valeri Bojarski</Authors>
<Company>Hensel Recycling GmbH</Company>
<Version>1.4.6</Version>
<Description>Json Web Token (JWT) &amp; LDAP user authentication
</Description>
</PropertyGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="IdentityServer4.Storage" Version="4.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.20" />
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="7.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.6.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,21 @@
using Newtonsoft.Json;
namespace HRD.LDAPService.JWT
{
public class HttpErrorDetails
{
public HttpErrorDetails(int statusCode, string message)
{
StatusCode = statusCode;
Message = message;
}
public string Message { get; set; }
public int StatusCode { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
}

View File

@@ -0,0 +1,40 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
namespace HRD.LDAPService.JWT
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class JWTAuthorizeAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
if (JwtTokenConfig.AktivateAuthorizationFilter)
{
bool isInWhiteList = false;
//allow access with logn & pwd and without Authorization token
var path = context?.HttpContext.Request.Path.Value;
if (!string.IsNullOrEmpty(path))
{
if (JwtTokenConfig.IsInBlackList(path))
{
context.Result = new JsonResult(new { message = $"Unauthorized access. Path is in a blacklist: '${path}'" }) { StatusCode = StatusCodes.Status403Forbidden };
}
isInWhiteList = JwtTokenConfig.IsInWhiteList(path);
if (!isInWhiteList)
{ //need jwt check
var check = (string)context.HttpContext.Items[JwtGlobals.HttpContextItem_IsValidHenselToken];
if (check == null)
{
context.Result = new JsonResult(new { message = $"Unauthorized access. Path: '${path}'" }) { StatusCode = StatusCodes.Status401Unauthorized };
}
}
}
}
}
}
}

View File

@@ -0,0 +1,125 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace HRD.LDAPService.JWT
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class JWTAuthorizeVendorId : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
if (JwtTokenConfig.AktivateAuthorizationFilter)
{
//allow access with logn & pwd and without Authorization token
var path = context?.HttpContext.Request.Path.Value;
if (!string.IsNullOrEmpty(path))
{
if (JwtTokenConfig.IsInBlackList(path))
{
context.Result = new JsonResult(new { message = $"Unauthorized access. Path is in a blacklist: '${path}'" }) { StatusCode = StatusCodes.Status403Forbidden };
return;
}
if (JwtTokenConfig.IsInWhiteList(path))
{
return;
}
else //need jwt check
{
var check = (string)context.HttpContext.Items[JwtGlobals.HttpContextItem_IsValidHenselToken];
if (check == null)
{
context.Result = new JsonResult(new { message = $"Unauthorized access. Path: '${path}'" }) { StatusCode = StatusCodes.Status401Unauthorized };
return;
}
}
var headerAuthorization = context.HttpContext.Request.Headers["Authorization"];
var authorizationType = headerAuthorization.FirstOrDefault()?.Split(" ").First();
if (authorizationType == null)
{
context.Result = new JsonResult(new { message = $"Eror. Path: '${path}'" }) { StatusCode = StatusCodes.Status401Unauthorized };
return;
}
var jwt = headerAuthorization.FirstOrDefault();
if (!JwtManager.IsValidatJwtTokenSubject(jwt))
{
throw new UnauthorizedAccessException($"Not valid JWT");
}
LdapUser ldapUser = JwtManager.DecryptTokenAsLdapUser(jwt);
string ldapUserVendorId = ldapUser.GetExtendedAttributeValue("VendorId");
if (string.IsNullOrEmpty(ldapUserVendorId))
{
context.Result = new JsonResult(new { message = $"Vendor Id is empty. Path: '${path}'" }) { StatusCode = StatusCodes.Status401Unauthorized };
return;
}
var syncIOFeature = context.HttpContext.Features.Get<IHttpBodyControlFeature>();
if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
var req = context.HttpContext.Request;
req.EnableBuffering();
// read the body here as a workarond for the JSON parser disposing the stream
if (req.Body.CanSeek)
{
req.Body.Seek(0, SeekOrigin.Begin);
// if body (stream) can seek, we can read the body to a string for logging purposes
using (var reader = new StreamReader(
req.Body,
encoding: Encoding.UTF8,
detectEncodingFromByteOrderMarks: false,
bufferSize: 8192,
leaveOpen: true))
{
var jsonString = reader.ReadToEnd();
var content = JsonConvert.DeserializeObject<dynamic>(jsonString);
if (content == null)
{
context.Result = new JsonResult(new { message = $"Unauthorized access. Can not deserialize the the Request: '${path}'" }) { StatusCode = StatusCodes.Status403Forbidden };
}
if (content?.Root != null && string.Equals(content?.Root?.Type.ToString(), "Array", StringComparison.InvariantCulture))
{
List<dynamic> contentList = JsonConvert.DeserializeObject<List<dynamic>>(jsonString);
string jwtVendorId = contentList?.FirstOrDefault()?.vendorId;
if (string.IsNullOrEmpty(jwtVendorId) || ldapUserVendorId != jwtVendorId)
{
context.Result = new JsonResult(new { message = $"Vendor {ldapUserVendorId} is not equal to Vendor from Token {jwtVendorId} List. Path: '${path}'" }) { StatusCode = StatusCodes.Status401Unauthorized };
return;
}
}
else
{
string jwtVendorId = content.vendorId;
if (string.IsNullOrEmpty(jwtVendorId) || ldapUserVendorId != jwtVendorId)
{
context.Result = new JsonResult(new { message = $"Vendor {ldapUserVendorId} is not equal to Vendor from Token {jwtVendorId}. Path: '${path}'" }) { StatusCode = StatusCodes.Status401Unauthorized };
return;
}
}
}
// Important! go back to beginning so json reader get's the whole thing
req.Body.Seek(0, SeekOrigin.Begin);
}
}
}
}
}
}
}

View File

@@ -0,0 +1,31 @@
namespace HRD.LDAPService.JWT
{
public static class JWTCrypt
{
public static string GenerateHashPassword(string inputKey)
{
return BCrypt.Net.BCrypt.EnhancedHashPassword(inputKey, 11, BCrypt.Net.HashType.SHA512);
}
public static bool VerifyHashPassword(string hashedPassword, string providedPassword)
{
return BCrypt.Net.BCrypt.Verify(providedPassword, hashedPassword, true, BCrypt.Net.HashType.SHA512);
}
public static string SHA512(string input)
{
var bytes = System.Text.Encoding.UTF8.GetBytes(input);
using (var hash = System.Security.Cryptography.SHA512.Create())
{
var hashedInputBytes = hash.ComputeHash(bytes);
// Convert to text
// StringBuilder Capacity is 128, because 512 bits / 8 bits in byte * 2 symbols for byte
var hashedInputStringBuilder = new System.Text.StringBuilder(128);
foreach (var b in hashedInputBytes)
hashedInputStringBuilder.Append(b.ToString("X2"));
return hashedInputStringBuilder.ToString();
}
}
}
}

View File

@@ -0,0 +1,19 @@
namespace HRD.LDAPService.JWT
{
public static class JwtGlobals
{
public const string HttpContextItem_LdapUser = "ldapuser";
public const string HttpContextItem_IsValidHenselToken = "IsValidHenselToken";
public const string CLAIM_DEPARTNENTID = "departmentid";
public const string CLAIM_EXTENDETDEPARTNENTIDLIST = "extendetdepartmentidlist";
public const string CLAIM_ROLE = "role";
public const string ROLE_USER = "User";
public const string ROLE_DEPARTMENTUSER = "DepartmentUser";
public const string ROLE_DEPARTMENTMASTER = "DepartmentMaster";
public const string ROLE_MASTER = "Master";
public const string ROLE_ADMIN = "Admin";
}
}

View File

@@ -0,0 +1,355 @@
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
namespace HRD.LDAPService.JWT
{
public static class JwtManager
{
private const string GlbExtendedAttributes = "ExtendedAttributes_";
public static LdapUser DecryptTokenAsLdapUser(string token)
{
if (string.IsNullOrEmpty(token)) { return default; }
//Check token with "Bearer" prefix
if (token.StartsWith("Bearer", StringComparison.InvariantCultureIgnoreCase))
{
token = token.Split(" ").Last();
}
if (string.IsNullOrEmpty(token)) { return default; }
JwtSecurityToken jwtSecurityToken = DecryptToken(token);
if (jwtSecurityToken == null) { return default; }
LdapUser ldapUser = ClaimsIdentityToLdapUser(jwtSecurityToken.Claims.ToList());
if (ldapUser == null)
{
return default;
}
ldapUser.Token = token;
return ldapUser;
}
public static JwtSecurityToken DecryptToken(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(JwtTokenConfig.Secret);
try
{
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.FromSeconds(60) // set clockskew to zero so tokens expire exactly at token expiration time
}, out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;
return jwtToken;
}
//IDX10223: Lifetime validation failed. The token is expired. ValidTo: 'System.DateTime', Current time: 'System.DateTime'.
catch (SecurityTokenExpiredException ex)
{
throw ex;
}
catch (Exception ex)
{
// return null if validation fails
throw ex;
}
}
public static LdapUser RenewLdapUserWithJwtToken(string token)
{
LdapUser renewLdapUser = null;
try
{
if (string.IsNullOrEmpty(token))
{
throw new ArgumentNullException($"Token is missing!");
}
renewLdapUser = LdapAuthenticationService.RenewIdentity(token);
if (renewLdapUser is null)
{
throw new Exception($"Can't renew from token!");
}
if (!renewLdapUser.IsValidatCredentials)
{
throw new Exception($"Invalid credentials!");
}
if (!renewLdapUser.Enabled)
{
throw new Exception($"Ldap-User is disabled!");
}
(string newtoken, DateTime newExpiredOn) = CreateToken(renewLdapUser);
renewLdapUser.Token = newtoken;
renewLdapUser.JwtExpiredOn = newExpiredOn;
if (!renewLdapUser.IsValid())
{
throw new Exception($"Ldapuser is not valid!");
}
return renewLdapUser;
}
catch (Exception ex)
{
throw ex;
}
}
public static LdapUser RenewLdapUserWithJwtToken(LdapUser ldapUser)
{
LdapUser renewLdapUser = null;
try
{
if (string.IsNullOrEmpty(ldapUser?.Token))
{
throw new Exception($"Token is missing (Login:{ldapUser.LoginName})");
}
renewLdapUser = LdapAuthenticationService.RenewIdentity(ldapUser);
if (renewLdapUser is null)
{
return default;
}
//if (!ldapUser.IsValidatCredentials)
//{
// ldapUser.Token = string.Empty;
// return false;
//}
if (!renewLdapUser.Enabled)
{
renewLdapUser.Token = string.Empty;
return renewLdapUser;
}
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(JwtTokenConfig.Secret);
var claims = CreateClaimsIdentity(renewLdapUser);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = claims,
Expires = DateTime.UtcNow.AddMinutes(JwtTokenConfig.ExpirationInMin),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
ldapUser.Token = tokenHandler.WriteToken(token);
ldapUser.JwtExpiredOn = token.ValidTo;
if (renewLdapUser.IsValid())
{
return renewLdapUser;
}
return default;
}
catch (Exception ex)
{
throw ex;
}
}
public static bool GenerateLdapUserWithJwtToken(LdapUser ldapUser)
{
try
{
if (!LdapAuthenticationService.CheckAndUpdateIdentityWithPassword(ldapUser))
{
return false;
}
if (!ldapUser.IsValidatCredentials)
{
ldapUser.Token = string.Empty;
return false;
}
if (!ldapUser.Enabled)
{
ldapUser.Token = string.Empty;
return false;
}
(string token, DateTime jwtExpiredOn) = CreateToken(ldapUser);
ldapUser.Token = token;
ldapUser.JwtExpiredOn = jwtExpiredOn;
return ldapUser.IsValid();
}
catch (Exception ex)
{
throw ex;
}
}
public static string GenerateHash(string password)
{
return JWTCrypt.SHA512(password);
}
private static (string, DateTime) CreateToken(LdapUser ldapUser)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(JwtTokenConfig.Secret);
var claims = CreateClaimsIdentity(ldapUser);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = claims,
Expires = DateTime.UtcNow.AddMinutes(JwtTokenConfig.ExpirationInMin),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return (tokenHandler.WriteToken(token), token.ValidTo);
}
public static bool IsValidatJwtTokenSubject(string token)
{
if (string.IsNullOrEmpty(token))
{
return false;
}
token = token.Trim();
if (token.IndexOf(" ", StringComparison.InvariantCultureIgnoreCase) > 0)
{
if (token.StartsWith("Bearer", StringComparison.InvariantCultureIgnoreCase)) //token with "Bearer" prefix
{
token = token.Split(" ").Last();
}
else
{
token = token.Split(" ").First();
}
}
try
{
var jwtToken = DecryptToken(token);
return !String.IsNullOrEmpty(jwtToken?.Subject); //Loginname
}
catch (Exception ex)
{
throw ex;
}
}
private static LdapUser ClaimsIdentityToLdapUser(List<Claim> claims)
{
LdapUser user = new LdapUser("");
foreach (var claim in claims)
{
switch (claim.Type)
{
case JwtRegisteredClaimNames.Sub:
user.LoginName = claim.Value;
break;
case JwtRegisteredClaimNames.Email:
user.Email = claim.Value;
break;
case JwtRegisteredClaimNames.NameId:
{
if (int.TryParse(claim.Value, out int id))
{
user.UserId = id;
}
}
break;
case JwtRegisteredClaimNames.Jti:
{
if (Guid.TryParse(claim.Value, out Guid g))
{
user.LdapGuid = g;
}
}
break;
case JwtGlobals.CLAIM_DEPARTNENTID:
user.DepartmentId = int.Parse(claim.Value);
break;
case JwtGlobals.CLAIM_EXTENDETDEPARTNENTIDLIST:
user.ExtendedDepartmentIdList = claim.Value;
break;
case JwtGlobals.CLAIM_ROLE:
user.AddRole(claim.Value);
break;
case JwtRegisteredClaimNames.Exp:
{
//#pragma warning disable CA1305 // Specify IFormatProvider
var expValue = Convert.ToInt32(claim.Value);
//#pragma warning restore CA1305 // Specify IFormatProvider
DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(expValue);
user.JwtExpiredOn = dateTimeOffset.UtcDateTime;
}
break;
case var s when claim.Type.StartsWith(GlbExtendedAttributes):
var strKey = claim.Type.Substring(GlbExtendedAttributes.Length, claim.Type.Length - GlbExtendedAttributes.Length);
user.ExtendedAttributesList.Add(new KeyValuePair<string, string>(strKey, claim.Value));
break;
default:
break;
}
}
return user;
}
private static ClaimsIdentity CreateClaimsIdentity(LdapUser user)
{
ClaimsIdentity claimsIdentity = new ClaimsIdentity();
List<Claim> claims = new List<Claim>
{
CreateClaim(JwtRegisteredClaimNames.Sub, user.LoginName),
CreateClaim(JwtRegisteredClaimNames.NameId, user.UserId),
CreateClaim(JwtRegisteredClaimNames.Email, user.Email),
CreateClaim(JwtGlobals.CLAIM_DEPARTNENTID, user.DepartmentId),
CreateClaim(JwtGlobals.CLAIM_EXTENDETDEPARTNENTIDLIST, user.ExtendedDepartmentIdList)
};
user.RoleList.ForEach(role => claims.Add(
CreateClaim(ClaimTypes.Role, role.Role)
));
user.ExtendedAttributesList.ForEach(item => claims.Add(
CreateClaim($"{GlbExtendedAttributes}{item.Key}", item.Value)
));
claimsIdentity.AddClaims(claims);
return claimsIdentity;
}
private static Claim CreateClaim(string claimName, int claimValue)
{
return new Claim(claimName, string.IsNullOrEmpty($"{claimValue}") ? string.Empty : $"{claimValue}");
}
private static Claim CreateClaim(string claimName, string claimValue)
{
return new Claim(claimName, string.IsNullOrEmpty(claimValue) ? string.Empty : claimValue);
}
}
}

View File

@@ -0,0 +1,97 @@
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Net.Mime;
using System.Threading.Tasks;
namespace HRD.LDAPService.JWT
{
public class JwtMiddleware
{
private readonly RequestDelegate _next;
public JwtMiddleware(RequestDelegate next)
{
_next = next;
}
#pragma warning disable AMNF0001 // Asynchronous method name is not ending with 'Async'
public async Task Invoke(HttpContext httpContext)
#pragma warning restore AMNF0001 // Asynchronous method name is not ending with 'Async'
{
if (httpContext == null)
{
throw new ArgumentNullException($"Jwt {httpContext} is null");
}
if (JwtTokenConfig.AktivateAuthorizationFilter)
{
var path = httpContext.Request.Path.Value;
if (!string.IsNullOrEmpty(path))
{
if (JwtTokenConfig.IsInBlackList(path))
{
httpContext.Response.ContentType = MediaTypeNames.Application.Json;
httpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
var responseJson = JsonConvert.SerializeObject($"Path is in a blacklist: '${path}'");
await httpContext.Response.WriteAsync(responseJson).ConfigureAwait(false);
return;
}
if (JwtTokenConfig.IsInWhiteList(path))
{
await _next(httpContext).ConfigureAwait(false); // calling next middleware
return;
}
}
}
var headerAuthorization = httpContext.Request.Headers["Authorization"];
var authorizationType = headerAuthorization.FirstOrDefault()?.Split(" ").First();
if (authorizationType == null)
{
await _next(httpContext).ConfigureAwait(false); // calling next middleware
return;
}
var jwt = headerAuthorization.FirstOrDefault();
//Check token
if (JwtManager.IsValidatJwtTokenSubject(jwt))
{
var user = JwtManager.DecryptTokenAsLdapUser(jwt);
if (user == default)
{
httpContext.Response.ContentType = MediaTypeNames.Application.Json;
httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
var responseJson = JsonConvert.SerializeObject($"Failed to decode JWT. The User was not valid");
await httpContext.Response.WriteAsync(responseJson).ConfigureAwait(false);
return;
}
httpContext.Items[JwtGlobals.HttpContextItem_IsValidHenselToken] = "true";
httpContext.Items[JwtGlobals.HttpContextItem_LdapUser] = user;
await _next(httpContext).ConfigureAwait(false); // calling next middleware
return;
}
else
{
httpContext.Response.ContentType = MediaTypeNames.Application.Json;
httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
var responseJson = JsonConvert.SerializeObject($"The JWT was not valid.");
await httpContext.Response.WriteAsync(responseJson).ConfigureAwait(false);
return;
}
}
private string GetAction(HttpContext httpContext)
{
if (httpContext.Request.Headers.ContainsKey("action"))
{
return httpContext.Request.Headers["action"].ToString();
}
return string.Empty;
}
}
}

View File

@@ -0,0 +1,69 @@
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Security.Claims;
using System.Text;
namespace HRD.LDAPService.JWT
{
public static class JwtMiddlewareExtensions
{
public static IApplicationBuilder UseJwtMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<JwtMiddleware>();
}
public static void ConfigureJWT(this IServiceCollection services, JwtMiddlewareOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
JwtTokenConfig.DeaktivateLDAP = options.DeaktivateLDAP; //if true => use login + pwd only
JwtTokenConfig.Secret = options.Secret;
JwtTokenConfig.Issuer = options.Issuer;
JwtTokenConfig.Audience = options.Audience;
JwtTokenConfig.JwtRoleList = options.JwtRoleList;
JwtTokenConfig.ExpirationInMin = options.ExpirationInMin;
JwtTokenConfig.AktivateAuthorizationFilter = options.AktivateAuthorizationFilter;
JwtTokenConfig.AuthorizationFilterWhitelistPath = options.AuthorizationFilterWhitelistPath;
JwtTokenConfig.AuthorizationFilterBlacklistPath = options.AuthorizationFilterBlacklistPath;
//Authentication
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
//JwtBearer
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.RequireHttpsMetadata = true;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = JwtTokenConfig.Issuer, //JWT-Site
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(JwtTokenConfig.Secret)),
ValidAudience = JwtTokenConfig.Audience,
ValidateAudience = true, //App-Site
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(1),
NameClaimType = ClaimTypes.NameIdentifier
};
});
//Authorization
services.AddAuthorization(authopt =>
{
authopt.AddPolicy("UserMustHaveRole", polBuilder => polBuilder.RequireClaim(ClaimTypes.Role));
});
}
}
}

View File

@@ -0,0 +1,18 @@
using System.Collections.Generic;
namespace HRD.LDAPService.JWT
{
public class JwtMiddlewareOptions
{
public string Secret { get; set; }
public int ExpirationInMin { get; set; } = 60 * 24 * 28; //28 Tage
public List<JwtRole> JwtRoleList { get; set; }
public List<string> AuthorizationFilterWhitelistPath { get; set; }
public List<string> AuthorizationFilterBlacklistPath { get; set; }
public bool AktivateAuthorizationFilter { get; set; } = true;
public string Issuer { get; set; }
public string Audience { get; set; }
public bool DeaktivateLDAP { get; set; }
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.ComponentModel.DataAnnotations;
namespace HRD.LDAPService
{
public class JwtRole
{
private string role;
private string _group;
public JwtRole(string role) : this(role, string.Empty)
{ }
public JwtRole(string role, string group)
{
Role = role;
Group = group;
}
[Required]
public string Role { get => role; set => role = value; }
[Required]
public string Group
{
get => _group;
//"dhr/" prefix should be removed
set => _group = string.IsNullOrEmpty(value) ? string.Empty : value.Replace(@"DHR\", "", StringComparison.InvariantCultureIgnoreCase);
}
}
}

View File

@@ -0,0 +1,49 @@
using System.Collections.Generic;
namespace HRD.LDAPService.JWT
{
public static class JwtTokenConfig
{
private static string secret;
public static int ExpirationInMin { get; set; }
public static string Secret { get; set; }
public static string Issuer { get; internal set; }
public static string Audience { get; internal set; }
#warning use internal setter
public static List<JwtRole> JwtRoleList { get; set; } = new List<JwtRole>();
public static List<string> AuthorizationFilterWhitelistPath { get; set; }
public static List<string> AuthorizationFilterBlacklistPath { get; set; }
public static bool AktivateAuthorizationFilter { get; set; }
public static bool DeaktivateLDAP { get; set; }
public static bool IsInWhiteList(string path)
{
if (string.IsNullOrEmpty(path)) { return false; }
foreach (var item in JwtTokenConfig.AuthorizationFilterWhitelistPath)
{
if (path.Contains(item, System.StringComparison.InvariantCultureIgnoreCase))
{
return true;
}
}
return false;
}
public static bool IsInBlackList(string path)
{
if (string.IsNullOrEmpty(path)) { return false; }
foreach (var item in JwtTokenConfig.AuthorizationFilterBlacklistPath)
{
if (path.Contains(item, System.StringComparison.InvariantCultureIgnoreCase))
{
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,9 @@
namespace HRD.LDAPService
{
public enum EN_LdapRoleListFilter
{
All = 1,
OnlyRoleList = 2,
OnlyWebAppRoleList = 3
}
}

View File

@@ -0,0 +1,213 @@
using HRD.LDAPService.JWT;
using System;
using System.DirectoryServices.AccountManagement;
using System.Linq;
namespace HRD.LDAPService
{
public static class LdapAuthenticationService
{
private const string LDAP_DOMAIN = "dhr.local";
private static UserPrincipal GetUserPrincipal(string loginName, PrincipalContext principalContext)
{
try
{
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, loginName);
if (userPrincipal == null)
{
userPrincipal = UserPrincipal.FindByIdentity(principalContext, loginName);
if (userPrincipal == null)
{
throw new Exception($"Can't find an user by name: '{loginName}'");
}
}
return userPrincipal;
}
catch (Exception ex)
{
throw new Exception($"Login failed wrong user credentials '{loginName}'", ex);
}
}
/// <summary>
/// Returns a User without LDAP user authentication
/// </summary>
/// <param name="ldapUser"></param>
/// <returns></returns>
public static LdapUser RenewIdentity(string token)
{
if (string.IsNullOrEmpty(token)) { throw new ArgumentNullException("Token is empty!"); }
try
{
LdapUser ldapUserFromToken = JwtManager.DecryptTokenAsLdapUser(token);
if (ldapUserFromToken == default)
{
throw new Exception($"Wrong token");
}
using PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, LDAP_DOMAIN);
ldapUserFromToken.IsValidatCredentials = true;
UpdateLdapUserFromPrincipalContext(ref ldapUserFromToken, principalContext);
return ldapUserFromToken;
}
catch (Exception ex)
{
throw new Exception($"Renew failed", ex);
}
}
/// <summary>
/// Returns a User without LDAP user authentication
/// </summary>
/// <param name="ldapUser"></param>
/// <returns></returns>
public static LdapUser RenewIdentity(LdapUser ldapUser)
{
if (ldapUser == default) { return default; }
try
{
if (String.IsNullOrEmpty(ldapUser.LoginName))
{
throw new Exception($"Renew Login failed empty user Loginname");
}
LdapUser ldapUserFromToken = JwtManager.DecryptTokenAsLdapUser(ldapUser.Token);
if (ldapUserFromToken == default)
{
throw new Exception($"Wrong token");
}
if (!string.Equals(ldapUserFromToken.LoginName, ldapUser.LoginName, StringComparison.OrdinalIgnoreCase))
{
throw new Exception($"Loginname and Token-Loginname are not the same");
}
if (ldapUser.IsRealLDAPUser)
{
ldapUserFromToken.IsRealLDAPUser = ldapUser.IsRealLDAPUser;
using PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, LDAP_DOMAIN);
ldapUser.IsValidatCredentials = true;
UpdateLdapUserFromPrincipalContext(ref ldapUserFromToken, principalContext);
}
else
{
ldapUserFromToken.IsRealLDAPUser = false;
ldapUserFromToken.AddPasswordHash(ldapUser.PasswordHash);
if (!string.Equals(ldapUserFromToken.PasswordHashShort, ldapUser.PasswordHashShort, StringComparison.OrdinalIgnoreCase))
{
throw new Exception($"PasswordHashShort and Token-PasswordHashShortare not the same");
}
ldapUserFromToken.IsValidatCredentials = !string.IsNullOrEmpty(ldapUserFromToken.PasswordHash);
ldapUserFromToken.Enabled = ldapUserFromToken.IsValidatCredentials;
ldapUserFromToken.BadLogonCount = ldapUserFromToken.IsValidatCredentials ? 0 : ldapUserFromToken.BadLogonCount + 1;
//ldapUserFromToken.IsAccountLockedOut = ;
//ldapUserFromToken.LdapName = ;
//ldapUserFromToken.LdapSurname = ;
//ldapUserFromToken.LdapGuid = ;
//ldapUserFromToken.Email = ;
//ldapUserFromToken.AccountLockoutTime = ;
}
return ldapUserFromToken;
}
catch (Exception ex)
{
throw new Exception($"Login failed wrong user credentials '{ldapUser.LoginName}'", ex);
}
}
/// <summary>
/// Returns a User after LDAP user authentication
/// </summary>
/// <param name="ldapUser"></param>
/// <returns></returns>
public static bool CheckAndUpdateIdentityWithPassword(LdapUser ldapUser)
{
if (ldapUser == default) { return false; }
try
{
if (String.IsNullOrEmpty(ldapUser.LoginName))
{
throw new Exception($"Login failed wrong user Loginname");
}
if (!JwtTokenConfig.DeaktivateLDAP)
{
ldapUser.IsRealLDAPUser = true;
using var principalContext = new PrincipalContext(ContextType.Domain, LDAP_DOMAIN);
//Check PWD
ldapUser.IsValidatCredentials = principalContext.ValidateCredentials(ldapUser.LoginName, ldapUser.Password);
UpdateLdapUserFromPrincipalContext(ref ldapUser, principalContext);
}
else
{
ldapUser.IsRealLDAPUser = false;
//ldapUser.AddPasswordHash(JWTCrypt.GenerateHashPassword(ldapUser.Password));
var hash = JWTCrypt.SHA512(ldapUser.Password);
ldapUser.AddPasswordHash(hash);
ldapUser.IsValidatCredentials = !string.IsNullOrEmpty(ldapUser.PasswordHash);
if (ldapUser.IsValidatCredentials)
{
ldapUser.Enabled = true;
ldapUser.BadLogonCount = 0;
ldapUser.LastBadPasswordAttempt = null;
}
else
{
ldapUser.Enabled = false;
ldapUser.BadLogonCount = +1;
ldapUser.LastBadPasswordAttempt = DateTime.UtcNow;
}
//ldapUser.IsAccountLockedOut = ;
//ldapUser.LdapName = ;
//ldapUser.LdapSurname = ;
//ldapUser.LdapGuid = ;
//ldapUser.Email = ;
//ldapUser.AccountLockoutTime = ;
}
return true;
}
catch (Exception ex)
{
ldapUser.IsValidatCredentials = false;
throw new Exception($"Login failed wrong user credentials '{ldapUser.LoginName}'", ex);
}
}
private static void UpdateLdapUserFromPrincipalContext(ref LdapUser ldapUser, PrincipalContext principalContext)
{
UserPrincipal userPrincipal = GetUserPrincipal(ldapUser.LoginName, principalContext);
if (userPrincipal == default)
{
throw new Exception($"Renew Login failed wrong user credentials '{ldapUser.LoginName}'");
}
ldapUser.IsAccountLockedOut = userPrincipal.IsAccountLockedOut();
ldapUser.BadLogonCount = userPrincipal.BadLogonCount;
ldapUser.Enabled = userPrincipal.Enabled ?? false;
ldapUser.LastBadPasswordAttempt = userPrincipal.LastBadPasswordAttempt;
ldapUser.LdapName = userPrincipal.Name;
ldapUser.LdapSurname = userPrincipal.Surname;
ldapUser.LdapGuid = userPrincipal.Guid;
ldapUser.Email = userPrincipal.EmailAddress;
ldapUser.AccountLockoutTime = userPrincipal.AccountLockoutTime;
ldapUser.RoleList = ldapUser.RoleList.Union(JWT.JwtTokenConfig.JwtRoleList).ToList();
if (ldapUser.RoleList?.Count > 0)
{
ldapUser = userPrincipal.Context.CheckAndAddGroupMembers(userPrincipal, ldapUser);
}
}
}
}

View File

@@ -0,0 +1,52 @@
using HRD.LDAPService.JWT;
using System;
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.Linq;
namespace HRD.LDAPService
{
public static class LdapExtensions
{
public static LdapUser CheckAndAddGroupMembers(this PrincipalContext context, UserPrincipal userPrincipal, LdapUser ldapUser)
{
if (context == null || userPrincipal == null || ldapUser == null)
{
throw new Exception($"UserPrincipal failed");
}
if (ldapUser.RoleList?.Count == 0)
{
ldapUser.RoleList = new List<JwtRole>();
return ldapUser;
}
try
{
List<Principal> userGroupList = userPrincipal.GetGroups().ToList(); // all groups of which the user is a direct member
List<JwtRole> jwtRoleList = ldapUser.RoleList; //keep all possible Roles of the user
List<JwtRole> fullRoleList = new List<JwtRole>();
fullRoleList = fullRoleList.Union(jwtRoleList).ToList(); //add Roles from backend
fullRoleList = fullRoleList.Union(JwtTokenConfig.JwtRoleList).ToList(); //add Roles from JwtTokenConfig.JwtRoleList
ldapUser.RoleList = new List<JwtRole>();
if (fullRoleList.Count > 0)
{
foreach (JwtRole jwtRole in jwtRoleList)
{
if (userGroupList.Exists(userGroup => userGroup.Name == jwtRole.Group))
{
ldapUser.AddRole(jwtRole.Role);
}
}
}
}
catch (Exception ex)
{
throw ex;
}
return ldapUser;
}
}
}

View File

@@ -0,0 +1,22 @@
namespace HRD.LDAPService
{
public static class LdapGlobals
{
private static bool _isLive;
public static bool LDAP_WebAppGroup_Is_Live { get => _isLive; set => _isLive = value; }
public const string LDAP_WINDREAM = "Windream_";
public const string LDAP_DOMAIN = "dhr.local";
public const string LDAP_PATH_EDM = "OU=DMS,OU=Gruppen,OU=DHDEAB,DC=dhr,DC=local";
public const string LDAP_PATH_WEBAPPS = "OU=Web-Apps,OU=Gruppen,OU=DHDEAB,DC=dhr,DC=local";
public const string LDAP_EDMUser_Prefix = "GG_EDMUser_Group";
public const string LDAP_EDMAdmin_Prefix = "GG_EDMAdmin_Group";
public const string LDAP_EDM_Prefix = "GG_EDM";
public const string LDAP_WebAppp_Prefix = "GG_WebApp";
public const string LDAP_Prefix_Test = "__Test";
}
}

View File

@@ -0,0 +1,265 @@
using System;
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.Linq;
namespace HRD.LDAPService
{
public static class LdapManager
{
public static bool AD_AddUserloginToGroup(string userLogin, string group4User)
{
string groupName = GetFullGroupName(group4User);
try
{
using (PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, LdapGlobals.LDAP_DOMAIN))
{
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, userLogin);
if (userPrincipal == default)
{
throw new Exception($". Can't find the UserPrincipal by userId:{userLogin}");
}
List<Principal> userGroupList = userPrincipal.GetGroups().ToList(); // all groups of which the user is a direct member
if (userGroupList == default)
{
throw new Exception($". Can't find the userGroupList; userId:{userLogin}");
}
GroupPrincipal userGroup = userGroupList.Find(x => string.Equals(x.Name, groupName, StringComparison.OrdinalIgnoreCase)) as GroupPrincipal;
if (userGroup != default)
{
return true; //is already here
}
else
{
GroupPrincipal group = GroupPrincipal.FindByIdentity(principalContext, IdentityType.Name, groupName);
if (group == default) //try to create a group
{
if (CreateAdGroup(groupName))
{
group = GroupPrincipal.FindByIdentity(principalContext, IdentityType.Name, groupName);
}
}
if (group == default)
{
throw new Exception($". Can't create the AD-group: \"{groupName}\"");
}
group.Members.Add(principalContext, IdentityType.SamAccountName, userLogin);
group.Save();
}
}
return true;
}
catch (Exception ex)
{
throw;
}
}
public static bool CheckAndCreateAdGroup(string adGroupName)
{
try
{
// set up domain context and binding to the OU=Web-Apps
var adPath = AD_GroupPath(adGroupName);
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, LdapGlobals.LDAP_DOMAIN, adPath))
{
var group = GroupPrincipal.FindByIdentity(ctx, IdentityType.Name, adGroupName);
if (group != null)
{
return true;
}
// create a new group principal, give it a name
GroupPrincipal newGroup = new GroupPrincipal(ctx, adGroupName);
// save the group
newGroup.Save();
return true;
}
}
catch (Exception ex)
{
return false;
//throw;
}
}
public static List<string> GetAdUserLoginList4AdGroups(List<string> adGroupNames)
{
if (adGroupNames == null) { return default; }
List<string> result = new List<string>();
foreach (var adGroupName in adGroupNames)
{
var list = GetAdUserLoginList4AdGroup(adGroupName);
result.AddRange(list);
}
return result;
}
public static List<string> GetAdUserLoginList4AdGroup(string adGroupName)
{
try
{
List<string> result = new List<string>();
// set up domain context and binding to the OU=Web-Apps
var adPath = AD_GroupPath(adGroupName);
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, LdapGlobals.LDAP_DOMAIN, adPath))
{
var group = GroupPrincipal.FindByIdentity(ctx, IdentityType.Name, adGroupName);
if (group == null)
{
throw new Exception($". Can't find the AD-group: \"{adGroupName}\"");
}
result = group.Members.Select(x => x.SamAccountName).ToList();
return result;
}
}
catch (Exception ex)
{
//_logger.LogException(ex, $"An error occurred while getting user for the AD-group {adGroupName}");
return default;
//throw;
}
}
public static bool CheckAndCreateAdGroups(List<string> adGroupNames)
{
if (adGroupNames == null) { return false; }
foreach (var adGroupName in adGroupNames)
{
if (!CheckAndCreateAdGroup(adGroupName))
{
return false;
}
}
return true;
}
public static bool CreateAdGroup(string adGroupName)
{
try
{
// set up domain context and binding to the OU=TechWriters organizational unit in your company
var adPath = AD_GroupPath(adGroupName);
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, LdapGlobals.LDAP_DOMAIN, adPath))
{
// create a new group principal, give it a name
using (GroupPrincipal group = new GroupPrincipal(ctx, adGroupName))
{
// optionally set additional properties on the newly created group here....
// save the group
group.Save();
}
return true;
}
}
catch (Exception)
{
return false;
//throw;
}
}
public static bool IsWindreamADGroup(string adGroupName)
{
return adGroupName.StartsWith(LdapGlobals.LDAP_EDM_Prefix, StringComparison.InvariantCultureIgnoreCase);
}
public static bool IsWindreamSuffixGroup(string suffixGroupName)
{
return suffixGroupName.StartsWith(LdapGlobals.LDAP_WINDREAM, StringComparison.InvariantCultureIgnoreCase);
}
public static bool IsWindreamAdminGroup(string suffixGroupName)
{
return suffixGroupName.StartsWith(LdapGlobals.LDAP_WINDREAM + "Admin", StringComparison.InvariantCultureIgnoreCase);
}
public static bool IsWindreamUserGroup(string suffixGroupName)
{
return suffixGroupName.StartsWith(LdapGlobals.LDAP_WINDREAM + "User", StringComparison.InvariantCultureIgnoreCase);
}
public static string AD_GroupPath(string adGroupName)
{
if (IsWindreamADGroup(adGroupName))
{
return LdapGlobals.LDAP_PATH_EDM;
}
else
{
return LdapGlobals.LDAP_PATH_WEBAPPS;
}
}
public static string GetFullGroupName(string groupNameSuffix)
{
//Mapping Windream_User => GG_EDMUser_Group_Live or GG_EDM__Test_User_Group
//Mapping Windream_Admin => GG_EDMAdmin_Group or GG_EDM__Test_Admin_Group
//Mapping Windream_Technik => GG_EDM_Technik or GG_EDM__Test_Technik
var testPrefix = !LdapGlobals.LDAP_WebAppGroup_Is_Live ? LdapGlobals.LDAP_Prefix_Test : "";
if (IsWindreamAdminGroup(groupNameSuffix))
{
return LdapGlobals.LDAP_EDMAdmin_Prefix + testPrefix;
}
else if (IsWindreamUserGroup(groupNameSuffix))
{
return LdapGlobals.LDAP_EDMUser_Prefix + testPrefix;
}
else
{
return (IsWindreamSuffixGroup(groupNameSuffix) ? LdapGlobals.LDAP_EDM_Prefix : LdapGlobals.LDAP_WebAppp_Prefix) + testPrefix + "_" + groupNameSuffix.Replace(LdapGlobals.LDAP_WINDREAM, "");
}
}
public static bool AD_RemoveUserFromGroup(string userId, string group4User)
{
string groupName = GetFullGroupName(group4User);
// secure that no windream user or admin can be deleted
if (groupName.Equals(LdapGlobals.LDAP_EDMUser_Prefix, StringComparison.CurrentCultureIgnoreCase)
|| groupName.Equals(LdapGlobals.LDAP_EDMAdmin_Prefix, StringComparison.CurrentCultureIgnoreCase))
{
return true;
}
try
{
using var principalContext = new PrincipalContext(ContextType.Domain, LdapGlobals.LDAP_DOMAIN);
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, userId);
if (userPrincipal == default)
{
throw new Exception($". Can't find the UserPrincipal by userId: {userId}");
}
List<Principal> userGroupList = userPrincipal.GetGroups().ToList(); // all groups of which the user is a direct member
if (userGroupList == default)
{
throw new Exception($". Can't find the userGroupList; userId: {userId}");
}
GroupPrincipal group = userGroupList.Find(x => x.Name == groupName) as GroupPrincipal;
if (group == default)
{
return true; //the user is not in the group - nothing to do more
//throw new Exception($". Can't find the AD-group: \"{groupName}\"");
}
group.Members.Remove(principalContext, IdentityType.SamAccountName, userId);
group.Save();
return true;
}
catch (Exception ex)
{
throw;
}
}
}
}

View File

@@ -0,0 +1,268 @@
using HRD.LDAPService.JWT;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Json.Serialization;
namespace HRD.LDAPService
{
public class LdapUser
{
private const string PASSWORD_HASH_SHORT = "PasswordHashShort";
public bool IsRealLDAPUser { get; set; }
public LdapUser()
{
}
public LdapUser(string loginName)
{
LoginName = loginName;
}
public LdapUser(string loginname, int userId, string password, int departmentId, string extendedDepartmentIdList, List<KeyValuePair<string, string>> extendedAttributesList = null) : base()
{
LoginName = loginname;
UserId = userId;
Password = password;
DepartmentId = departmentId;
ExtendedDepartmentIdList = extendedDepartmentIdList;
ExtendedAttributesList = extendedAttributesList == null ? new List<KeyValuePair<string, string>>() : extendedAttributesList;
}
public LdapUser(string loginname, int userId, string password)
{
LoginName = loginname;
UserId = userId;
Password = password;
}
#region Ldap Fields
public Guid? LdapGuid { get; internal set; }
public string LdapName { get; set; }
public string LdapSurname { get; set; }
#endregion Ldap Fields
public int DepartmentId { get; set; }
public bool IsValidatCredentials { get; set; }
public string Email
{
get; set; // { return $"{LoginName}@hensel-recycling.com"; }
}
public string ExtendedDepartmentIdList { get; set; }
public DateTime JwtExpiredOn { get; set; }
[Required]
public string LoginName { get; set; }
[JsonIgnore]
public string Password { get; set; }
[JsonIgnore]
public string PasswordHash { get; set; }
public List<KeyValuePair<string, string>> ExtendedAttributesList { get; set; } = new List<KeyValuePair<string, string>>();
public List<JwtRole> RoleList { get; set; } = new List<JwtRole>();
public string Token { get; set; }
public int UserId { get; set; }
public int BadLogonCount { get; set; }
public DateTime? LastBadPasswordAttempt { get; internal set; }
public string PasswordHashShort
{
get
{
if (PasswordHash?.Length <= 10) { return string.Empty; };
return PasswordHash.Substring(PasswordHash.Length - 10);
}
}
public string GetLastBadPasswordAttemptAsLocalTime()
{
if (LastBadPasswordAttempt == null)
{
return string.Empty;
}
return ((DateTime)LastBadPasswordAttempt).ToLocalTime().ToLongTimeString();
}
public void AddPasswordHash(string passwordHash)
{
PasswordHash = passwordHash;
if (!ExistsExtendedAttributeValue(PASSWORD_HASH_SHORT))
{
AddExtendedAttribute(PASSWORD_HASH_SHORT, PasswordHashShort);
}
}
public string GetExtendedAttributePasswordHash()
{
return GetExtendedAttributeValue(PASSWORD_HASH_SHORT);
}
public bool ExistsExtendedAttributeValue(string key)
{
foreach (var item in ExtendedAttributesList)
{
if (item.Key == key) { return true; }
}
return false;
}
public string GetExtendedAttributeValue(string key)
{
foreach (var item in ExtendedAttributesList)
{
if (item.Key == key) { return item.Value; }
}
return string.Empty;
}
public string GetAccountLockoutTimeAsLocalTime()
{
if (AccountLockoutTime == null)
{
return string.Empty;
}
return ((DateTime)AccountLockoutTime).ToLocalTime().ToLongTimeString();
}
public bool IsAccountLockedOut { get; internal set; }
public DateTime? AccountLockoutTime { get; internal set; }
public bool Enabled { get; set; }
public static bool IsJwtGlobalsRole(string roleName)
{
return string.Equals(roleName, JwtGlobals.ROLE_USER, StringComparison.OrdinalIgnoreCase)
|| string.Equals(roleName, JwtGlobals.ROLE_DEPARTMENTUSER, StringComparison.OrdinalIgnoreCase)
|| string.Equals(roleName, JwtGlobals.ROLE_DEPARTMENTMASTER, StringComparison.OrdinalIgnoreCase)
|| string.Equals(roleName, JwtGlobals.ROLE_MASTER, StringComparison.OrdinalIgnoreCase)
|| string.Equals(roleName, JwtGlobals.ROLE_ADMIN, StringComparison.OrdinalIgnoreCase);
}
public void AddExtendedAttribute(string key, string value)
{
ExtendedAttributesList.Add(new KeyValuePair<string, string>(key, value));
}
public void AddRole(JwtRole jwtRole)
{
if (!RoleList.Exists(x => x.Role == jwtRole.Role && x.Group == jwtRole.Group))
{
RoleList.Add(jwtRole);
}
}
public void AddRole(string role)
{
if (!string.IsNullOrEmpty(role) && !RoleList.Exists(x => x.Role == role))
{
RoleList.Add(new JwtRole(role));
}
}
public List<int> DepartmentIdListAll()
{
List<int> list = new List<int>() { DepartmentId };
if (!string.IsNullOrEmpty(ExtendedDepartmentIdList))
{
List<int> extendetList = ExtendedDepartmentIdList.Split(',').Select(x => int.Parse(x.Trim())).ToList();
list = list.Union(extendetList).ToList();
}
return list;
}
public bool IsAdmin()
{
return IsExistsRole(JwtGlobals.ROLE_ADMIN);
}
public bool IsDepartmentMaster()
{
return IsExistsRole(JwtGlobals.ROLE_DEPARTMENTMASTER);
}
public bool IsDepartmentUser()
{
return IsExistsRole(JwtGlobals.ROLE_DEPARTMENTUSER);
}
public bool IsExistsRole(string role)
{
return RoleList.Exists(x => String.Equals(x.Role, role, StringComparison.OrdinalIgnoreCase));
}
public bool IsMaster()
{
return IsExistsRole(JwtGlobals.ROLE_MASTER);
}
public bool IsUser()
{
return IsExistsRole(JwtGlobals.ROLE_USER);
}
public bool IsValid()
{
if (IsRealLDAPUser)
{
return !string.IsNullOrEmpty(LoginName)
//&& RoleList.Count > 0
&& (LdapGuid != null)
&& Enabled
&& IsValidatCredentials;
}
else
{
return !string.IsNullOrEmpty(LoginName)
&& Enabled
&& IsValidatCredentials;
}
}
public string RoleListAsString(EN_LdapRoleListFilter filter = EN_LdapRoleListFilter.All)
{
List<string> resultList = new List<string>();
foreach (var item in RoleList)
{
switch (filter)
{
case EN_LdapRoleListFilter.All:
resultList.Add(item.Role);
break;
case EN_LdapRoleListFilter.OnlyRoleList:
if (IsJwtGlobalsRole(item.Role)) { resultList.Add(item.Role); }
break;
case EN_LdapRoleListFilter.OnlyWebAppRoleList:
if (!IsJwtGlobalsRole(item.Role)) { resultList.Add(item.Role); }
break;
default:
break;
}
}
return string.Join(",", resultList);
}
public override string ToString()
{
return $"{this.LoginName}; Roles: {RoleList.Count}; ExtendedDepartmentIdList: {ExtendedDepartmentIdList}, ExtendedAttributesList: {ExtendedAttributesList} ";
}
}
}