Base solution for your next web application
Open Closed

Add windows authentication support #701


User avatar
0
ofir1234 created

Hi. I m using your module zero successfully for couple of months now. Thank you for that. I wonder if it's possible to add a windows authentication support. If I m creating a new ASP .NET project, I can choose in the right pane "windows authentication". But your template is already made, so how can I use some windows authentication features? For example, I would like to display "hello ezh276" where this name represents the windows login.

Thanks.


9 Answer(s)
  • User Avatar
    0
    hikalkan created
    Support Team

    Have you checked docs: <a class="postlink" href="http://www.aspnetboilerplate.com/Pages/Documents/Zero/User-Management#ldapactive-directory">http://www.aspnetboilerplate.com/Pages/ ... -directory</a>

  • User Avatar
    0
    ofir1234 created

    Looks nice. But one thing is missing. After I have configured everything like written in these docs (I m using the default settings with no domain name, password, etc because all of my users are already on a normal domain). Now, can you give an example command I need to use to extract the current "user name" inside an application service ? I can give you an example of the traditional way, using an API controller :

    var x = HttpContext.Current.User.Identity.Name
    

    But how can I do it now in an application service ? Is it possible ?

    Thanks

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    You can define an interface in the app layer to get username. Then you can implement it in the web layer (and register to DI) to get it from HttpContext.Current.User.Identity.Name. Then inject this interface wherever you need.

  • User Avatar
    0
    ofir1234 created

    Ok. So I've read the LDAP documentation and implemented exactly what's written in there, but still can't let my domain users log in. All of the computers in our company are part of a windows domain, so I can use the default settings and not change anything (as said in the documentation).

    So all I've done was this :

    Created this class in my Core project :

    public class MyLdapAuthenticationSource : LdapAuthenticationSource<Tenant, User>
    {
        public MyLdapAuthenticationSource(ILdapSettings settings, IAbpZeroLdapModuleConfig ldapModuleConfig)
            : base(settings, ldapModuleConfig)
        {
        }
    }
    

    Then, Added this line to my Core module:

    Configuration.Modules.ZeroLdap().Enable(typeof (MyLdapAuthenticationSource));
    

    But I'm still getting the login screen when running the solution, and if I enter (for example) my domain user name, it doesn't log in. I can only log in using the admin, 123qwe password.

    What have I missed ?

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    It's normal to get login screen since this is not Single sign-on. It just checks username/pass first from active directory. But, if you enter AD username and pass, then it should login. Probably, you missed to enable it for the current tenant in the settings. You can use Setting Manager (<a class="postlink" href="http://www.aspnetboilerplate.com/Pages/Documents/Setting-Management">http://www.aspnetboilerplate.com/Pages/ ... Management</a>) for that:

    await SettingManager.ChangeSettingForTenantAsync(AbpSession.GetTenantId(), LdapSettingNames.IsEnabled, "true");
    

    this code directly works in an application service. If you want to change setting in database, you can change it in AbpSettings table. Example, for the default tenant:

    [attachment=0:1ea0g4oy]ldap-enable.png[/attachment:1ea0g4oy]

    Note: Settings are maybe cached and you need to recycle your application.

  • User Avatar
    0
    ofir1234 created

    Wow ! So cool ! It's working !

    One last thing : Now that users can log-in using their domain username, I don't want this login screen. In our company, users always log-in using their own username and password, and they can't know the password of any other person in the company. This means that this screen is unnecessary. Is there a way to disable it, or maybe log-in automatically using this domain user (even the first time a user comes into my website) ? Maybe let them log out, but don't force them to enter their username and password for the first time they come into the site.

    Thanks a lot, I appreciate your work so much.

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    I'm not experienced with single sign on. This is a general topic, maybe you can search web for it. If you find a solution and you have a problem with implementing in within ABP, then please write again. Have a nice day.

  • User Avatar
    0
    ofir1234 created

    Hi. Your LDAP solution is working really good, although I've noticed one problem today. In our company, it is possible to get into the domain when you are not physically at the office (VPN). But it seems that the ASP.NET Boilerplate framework can't communicate with the LDAP server when I'm connecting from VPN. This means that no one can log- into my website when he is outside the office (and using the VPN), not even the admin user (admin,123qwe). When I'm on this VPN mode, I'm actually in the domain, and everything should work the same. But it doesn't, and no one can log in from outside, nor register a new user.

    Attaching the error message a user (which is trying to register) receives (when trying to connect it just says login failed):

    Server Error in '/' Application.
    
    The LDAP server is unavailable.
    
    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 
    
    Exception Details: System.DirectoryServices.Protocols.LdapException: The LDAP server is unavailable.
    
    Source Error: 
    
    
    Line 98:         private async Task<AbpUserManager<Tenant, Role, User>.AbpLoginResult> GetLoginResultAsync(string usernameOrEmailAddress, string password, string tenancyName)
    Line 99:         {
    Line 100:            var loginResult = await _userManager.LoginAsync(usernameOrEmailAddress, password, tenancyName);
    Line 101:
    Line 102:            switch (loginResult.Result)
    
    Source File: C:\Workspace\multiproject\myproject\myproject.Web\Controllers\AccountController.cs    Line: 100 
    
    Stack Trace: 
    
    
    [LdapException: The LDAP server is unavailable.]
       System.DirectoryServices.Protocols.LdapConnection.Connect() +79437
       System.DirectoryServices.Protocols.LdapConnection.SendRequestHelper(DirectoryRequest request, Int32& messageID) +212
       System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request, TimeSpan requestTimeout) +88
       System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request) +17
       System.DirectoryServices.AccountManagement.PrincipalContext.ReadServerConfig(String serverName, ServerProperties& properties) +363
    
    [PrincipalServerDownException: The server could not be contacted.]
       System.DirectoryServices.AccountManagement.PrincipalContext.ReadServerConfig(String serverName, ServerProperties& properties) +449
       System.DirectoryServices.AccountManagement.PrincipalContext.DoServerVerifyAndPropRetrieval() +64
       System.DirectoryServices.AccountManagement.PrincipalContext..ctor(ContextType contextType, String name, String container, ContextOptions options, String userName, String password) +285
       System.DirectoryServices.AccountManagement.PrincipalContext..ctor(ContextType contextType, String name, String container, String userName, String password) +56
       Abp.Zero.Ldap.Authentication.<CreatePrincipalContext>d__13.MoveNext() +1988
       System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
       System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
       System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +28
       Abp.Zero.Ldap.Authentication.&lt;TryAuthenticateAsync&gt;d__0.MoveNext() +502
       System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
       System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
       System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +28
       Abp.Authorization.Users.<TryLoginFromExternalAuthenticationSources>d__52.MoveNext() +643
       System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
       System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
       System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +28
       Abp.Authorization.Users.&lt;LoginAsync&gt;d__40.MoveNext() +1487
       System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
       System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
       System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +28
       myproject.Web.Controllers.<GetLoginResultAsync>d__10.MoveNext() in C:\Workspace\multiproject\myproject\myproject.Web\Controllers\AccountController.cs:100
       System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
       System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
       System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +28
       myproject.Web.Controllers.&lt;Register&gt;d__16.MoveNext() in C:\Workspace\multiproject\myproject\myproject.Web\Controllers\AccountController.cs:261
       System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
       System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
       System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +28
       Abp.Threading.<AwaitTaskWithPostActionAndFinallyAndGetResult>d__10`1.MoveNext() +575
       System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
       System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
       System.Runtime.CompilerServices.TaskAwaiter.GetResult() +26
       System.Threading.Tasks.TaskHelpersExtensions.ThrowIfFaulted(Task task) +42
       System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult) +73
       System.Web.Mvc.Async.&lt;&gt;c__DisplayClass37.&lt;BeginInvokeAsynchronousActionMethod&gt;b__36(IAsyncResult asyncResult) +37
       System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +27
       System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +58
       System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +68
       System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +34
       System.Web.Mvc.Async.AsyncInvocationWithFilters.&lt;InvokeActionMethodFilterAsynchronouslyRecursive&gt;b__3d() +69
       System.Web.Mvc.Async.&lt;&gt;c__DisplayClass46.&lt;InvokeActionMethodFilterAsynchronouslyRecursive&gt;b__3f() +230
       System.Web.Mvc.Async.&lt;&gt;c__DisplayClass33.&lt;BeginInvokeActionMethodWithFilters&gt;b__32(IAsyncResult asyncResult) +27
       System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +27
       System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +58
       System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +68
       System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
       System.Web.Mvc.Async.&lt;&gt;c__DisplayClass2b.&lt;BeginInvokeAction&gt;b__1c() +42
       System.Web.Mvc.Async.&lt;&gt;c__DisplayClass21.&lt;BeginInvokeAction&gt;b__1e(IAsyncResult asyncResult) +124
       System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +27
       System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +58
       System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +30
       System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +29
       System.Web.Mvc.Controller.&lt;BeginExecuteCore&gt;b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +27
       System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +48
       System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +58
       System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +30
       System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +21
       System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +32
       Castle.Proxies.AccountControllerProxy.EndExecuteCore_callback(IAsyncResult asyncResult) +4
       Castle.Proxies.Invocations.Controller_EndExecuteCore.InvokeMethodOnTarget() +55
       Castle.DynamicProxy.AbstractInvocation.Proceed() +86
       Abp.Domain.Uow.UnitOfWorkInterceptor.Intercept(IInvocation invocation) +97
       Castle.DynamicProxy.AbstractInvocation.Proceed() +114
       Castle.Proxies.AccountControllerProxy.EndExecuteCore(IAsyncResult asyncResult) +142
       System.Web.Mvc.Controller.&lt;BeginExecute&gt;b__15(IAsyncResult asyncResult, Controller controller) +26
       System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +40
       System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +58
       Castle.Proxies.AccountControllerProxy.EndExecute_callback(IAsyncResult asyncResult) +26
       Castle.Proxies.Invocations.Controller_EndExecute.InvokeMethodOnTarget() +55
       Castle.DynamicProxy.AbstractInvocation.Proceed() +86
       Abp.Domain.Uow.UnitOfWorkInterceptor.Intercept(IInvocation invocation) +97
       Castle.DynamicProxy.AbstractInvocation.Proceed() +114
       Castle.Proxies.AccountControllerProxy.EndExecute(IAsyncResult asyncResult) +142
       System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +24
       System.Web.Mvc.MvcHandler.&lt;BeginProcessRequest&gt;b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +27
       System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +48
       System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +58
       System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +30
       System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +21
       System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +29
       System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +23
       System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +129
    
    Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.6.1055.0
    

    Any suggestion ?

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    LDAP code is pretty simple (<a class="postlink" href="https://github.com/aspnetboilerplate/module-zero/blob/master/src/Abp.Zero.Ldap/Ldap/Authentication/LdapAuthenticationSource.cs#L116">https://github.com/aspnetboilerplate/mo ... ce.cs#L116</a>). So, I'm not sure that's related to module-zero code. If you directly use .NET's AD API (PrincipalContext), you will get the same exception. Do you know how to solve it? It's appriciated if you can share a solution with us.