Skip to content

Commit

Permalink
Feature/LDAP (#49)
Browse files Browse the repository at this point in the history
* README.md

* bug fix while migrating database

* LDAP feature
  • Loading branch information
brunobritodev committed May 10, 2020
1 parent 8a4dd7f commit 0c954c5
Show file tree
Hide file tree
Showing 15 changed files with 385 additions and 43 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using JPProject.Domain.Core.Bus;
using Jp.Api.Management.ViewModel;
using Jp.Ldap;
using JPProject.Domain.Core.Bus;
using JPProject.Domain.Core.Interfaces;
using JPProject.Domain.Core.Notifications;
using JPProject.Sso.Application.Interfaces;
Expand Down Expand Up @@ -47,6 +49,13 @@ public async Task<ActionResult> Update([FromBody] IEnumerable<ConfigurationViewM
return ResponsePutPatch();
}

[HttpGet("ldap-test")]
public ActionResult<LdapConnectionResult> TestLdapSettings([FromQuery] LdapSettingsTestQuery query)
{
var ldapTest = new LdapTestConnection(query.Get());
return ResponseGet(ldapTest.Test(query.Username, query.Password));

}

}
}
15 changes: 8 additions & 7 deletions src/Backend/Jp.Api.Management/Jp.Api.Management.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
<ItemGroup>
<PackageReference Include="Hellang.Middleware.ProblemDetails" Version="5.0.0" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="JPProject.Admin.Application" Version="3.2.6-prerelease1.04-19-014216" />
<PackageReference Include="JPProject.Admin.EntityFramework.Repository" Version="3.2.6-prerelease1.04-19-014216" />
<PackageReference Include="JPProject.Sso.Application" Version="3.2.6-prerelease1.04-19-014216" />
<PackageReference Include="JPProject.AspNet.Core" Version="3.2.6-prerelease1.04-19-014216" />
<PackageReference Include="JPProject.Admin.Application" Version="3.2.7" />
<PackageReference Include="JPProject.Admin.EntityFramework.Repository" Version="3.2.7" />
<PackageReference Include="JPProject.Sso.Application" Version="3.2.7" />
<PackageReference Include="JPProject.AspNet.Core" Version="3.2.7" />
<PackageReference Include="JpProject.AspNetCore.PasswordHasher.Argon2" Version="3.0.3" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.13.1" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.14.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.3" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.3" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.8" />
Expand All @@ -28,8 +28,8 @@
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="ServiceStack.Text" Version="5.8.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="5.3.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.3.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="5.4.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.4.1" />
</ItemGroup>

<ItemGroup Label="Tools">
Expand All @@ -41,6 +41,7 @@

<ItemGroup>
<ProjectReference Include="..\Jp.Database\Jp.Database.csproj" />
<ProjectReference Include="..\Jp.Ldap\Jp.Ldap.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
19 changes: 19 additions & 0 deletions src/Backend/Jp.Api.Management/ViewModel/LdapSettingsTestQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using JPProject.Sso.Domain.ViewModels.Settings;

namespace Jp.Api.Management.ViewModel
{
public class LdapSettingsTestQuery
{
public string Username { get; set; }
public string Password { get; set; }
public string DomainName { get; set; }
public string DistinguishedName { get; set; }
public string Attributes { get; set; }
public string AuthType { get; set; }
public string SearchScope { get; set; }
public LdapSettings Get()
{
return new LdapSettings(DomainName, DistinguishedName, Attributes, AuthType, SearchScope);
}
}
}
8 changes: 4 additions & 4 deletions src/Backend/Jp.Database/Jp.Database.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="IdentityServer4.EntityFramework" Version="3.1.2" />
<PackageReference Include="JPProject.Domain.Core" Version="3.2.6-prerelease1.04-19-014216" />
<PackageReference Include="JPProject.Sso.AspNetIdentity" Version="3.2.6-prerelease1.04-19-014216" />
<PackageReference Include="JPProject.Sso.EntityFramework.Repository" Version="3.2.6-prerelease1.04-19-014216" />
<PackageReference Include="IdentityServer4.EntityFramework" Version="3.1.3" />
<PackageReference Include="JPProject.Domain.Core" Version="3.2.7" />
<PackageReference Include="JPProject.Sso.AspNetIdentity" Version="3.2.7" />
<PackageReference Include="JPProject.Sso.EntityFramework.Repository" Version="3.2.7" />
<PackageReference Include="Jwks.Manager.Store.EntityFrameworkCore" Version="3.1.1" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="3.1.3" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.3" />
Expand Down
12 changes: 12 additions & 0 deletions src/Backend/Jp.Ldap/Jp.Ldap.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JPProject.Sso.Application" Version="3.2.7" />
<PackageReference Include="Microsoft.Windows.Compatibility" Version="3.1.0" />
</ItemGroup>

</Project>
60 changes: 60 additions & 0 deletions src/Backend/Jp.Ldap/LdapAuthentication.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using JPProject.Domain.Core.Util;
using JPProject.Sso.Application.ViewModels.UserViewModels;
using JPProject.Sso.Domain.ViewModels.Settings;
using System;
using System.DirectoryServices.Protocols;
using System.Linq;
using System.Net;
using System.Security.Claims;

namespace Jp.Ldap
{

public class LdapAuthentication
{
private readonly LdapSettings _settings;

public LdapAuthentication(LdapSettings settings)
{
_settings = settings;
}

public UserViewModel Login(string username, string password)
{
var credential = new NetworkCredential(username, password);
//var dcName = "brunobrito";
//var dcSufix = "net";

using var connection = new LdapConnection(_settings.DomainName);
if (_settings.AuthType.IsPresent() && Enum.TryParse(typeof(AuthType), _settings.AuthType, out _))
connection.AuthType = Enum.Parse<AuthType>(_settings.AuthType);

connection.Bind(credential);
//var _userStore = $"dc={dcName},dc={dcSufix}";
var searchFilter = $"(SAMAccountName={username})";

var attributes = _settings.Attributes?.Trim() == "" ? null : _settings.Attributes?.Split(",").Select(s => s.Trim());
var searchRequest = new SearchRequest
(
_settings.DistinguishedName,
searchFilter,
Enum.Parse<SearchScope>(_settings.SearchScope),
attributes?.ToArray()
//new string[] { "displayName", "cn", "mail" }
);
// null pega todos os campos
var response = (SearchResponse)connection.SendRequest(searchRequest);
var uservm = new UserViewModel() { UserName = username, Name = username};
foreach (SearchResultEntry entry in response.Entries)
{
foreach (DirectoryAttribute dirAttr in entry.Attributes.Values)
{
uservm.CustomClaims.Add(new Claim(dirAttr.Name, dirAttr[0].ToString()));
Console.WriteLine($"Attribute={dirAttr.Name},Value={dirAttr[0]}");
}
}

return uservm;
}
}
}
26 changes: 26 additions & 0 deletions src/Backend/Jp.Ldap/LdapConnectionResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using JPProject.Domain.Core.ViewModels;
using System.Collections.Generic;

namespace Jp.Ldap
{
public class LdapConnectionResult
{
public bool Success { get; }
public List<ClaimViewModel> Claims { get; }
public string Error { get; }
public string Step { get; }

public LdapConnectionResult(bool success, string error, string step)
{
Success = success;
Error = error;
Step = step;
}

public LdapConnectionResult(bool success, List<ClaimViewModel> claims)
{
Success = success;
Claims = claims;
}
}
}
77 changes: 77 additions & 0 deletions src/Backend/Jp.Ldap/TestConnection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using JPProject.Domain.Core.Util;
using JPProject.Domain.Core.ViewModels;
using JPProject.Sso.Domain.ViewModels.Settings;
using System;
using System.Collections.Generic;
using System.DirectoryServices.Protocols;
using System.Linq;
using System.Net;

namespace Jp.Ldap
{
public class LdapTestConnection
{
private readonly LdapSettings _settings;

public LdapTestConnection(LdapSettings settings)
{
_settings = settings;
}

public LdapConnectionResult Test(string username, string password)
{
var credential = new NetworkCredential(username, password);
//var dcName = "brunobrito";
//var dcSufix = "net";
LdapConnection connection;

try
{
connection = new LdapConnection(_settings.DomainName);
if (_settings.AuthType.IsPresent() && Enum.TryParse(typeof(AuthType), _settings.AuthType, out _))
connection.AuthType = Enum.Parse<AuthType>(_settings.AuthType);

connection.Bind(credential);
}
catch (Exception e)
{
return new LdapConnectionResult(false, e.Message, "Login");
}


//var _userStore = $"dc={dcName},dc={dcSufix}";
var searchFilter = $"(SAMAccountName={username})";

var attributes = _settings.Attributes?.Trim() == "" ? null : _settings.Attributes?.Split(",").Select(s => s.Trim());
var searchRequest = new SearchRequest
(
_settings.DistinguishedName,
searchFilter,
Enum.Parse<SearchScope>(_settings.SearchScope),
attributes?.ToArray()
//new string[] { "displayName", "cn", "mail" }
);

var claims = new List<ClaimViewModel>();
try
{
var response = (SearchResponse)connection.SendRequest(searchRequest);
foreach (SearchResultEntry entry in response.Entries)
{
foreach (DirectoryAttribute dirAttr in entry.Attributes.Values)
{
claims.Add(new ClaimViewModel(dirAttr.Name, dirAttr[0].ToString()));
}
}
}
catch (Exception e)
{
return new LdapConnectionResult(false, e.Message, "Search Error");
}

return new LdapConnectionResult(true, claims.OrderBy(b => b.Type).ToList());
}


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static IIdentityServerBuilder SetupKeyMaterial(this IIdentityServerBuilde
// https://tools.ietf.org/html/rfc7518#section-3.1
// While ES256 is most recommended, too many providers from another techies (Node, Java) made by companies like Okta, Auth0 doesn't support Elliptic Curves yet.
// So to increase compatibility we're changing algoritmo for RSA. PS256 is probabilistic like ES256 which guarantees a high degree of security as well.
// So to increase compatibility we're changing algorithm for RSA. PS256 is probabilistic like ES256 which guarantees a high degree of security as well.
// options.Algorithm = Algorithm.ES256;
options.Algorithm = Algorithm.PS256;
options.DaysUntilExpire = 90;
Expand Down

0 comments on commit 0c954c5

Please sign in to comment.