Skip to end of metadata
Go to start of metadata

The article describes the list of steps necessary to set up auto login on a system using Kerberos authentication in a Windows environment.

Step-by-step guide

  1. Get the required information:

    1. domain name
    2. the address of the domain controller (e.g. using the echo %logonserver% command)
    3. the name and password of the account used to communicate with the domain controller

    4. the address of the server that will be used to test the solution
    5. the test account that is in the domain
  2. Make sure that the SPN (Service Principal Name) for the account used to communicate with the domain controller has been properly configured on the domain controller

    To view all SPNs for a given account: setspn /l <domain>\<user>

    To register the required SPNs for a given account:
    setspn -s HTTP/<PlusWorkflow server name> <domain>\<user>
    setspn -s HTTP/<PlusWorkflow server name>.<domain> <domain>\<user>

    eg.

    setspn -s HTTP/plusworkflow_test suncode\ldap_account
    setspn -s HTTP/plusworkflow_test.suncode.com suncode\ldap_account

  3. Add a test account that is in your domain to the PlusWorkflow system

    1. login: <domain>/<user>
    2. leave the password blank
  4. Add a LDAP server to the PlusWorkflow system in Administration -> System Configuration -> LDAP Servers
  5. In the system parameters, enable auto login and set the account to connect to the domain controller

  6. Modify the WEB-INF/krb5.conf file

    [libdefaults]
    	default_tkt_enctypes = aes256-cts-hmac-sha1-96 aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc
    	default_tgs_enctypes = aes256-cts-hmac-sha1-96 aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc
    	permitted_enctypes   = aes256-cts-hmac-sha1-96 aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc 
    	default_realm = suncode.com
    [realms]
    	suncode.com  = {
    		kdc = KDC.suncode.com
    		default_domain = suncode.com 
    }
    [domain_realm]
    	.suncode.com = suncode.com
    	suncode.com = suncode.com	

    where:

    kdc = FQDN for Key Distribution Center (most likely domain controller)
    default_tkt_enctypes orad default_tgs_enctypes = available ticket encryption algorithms

    It is recommended to move the krb5.conf file to the <plusworkflow.home>/config/kerberos/krb5.conf location. This eliminates the need to store this file in the client project. The system reads this file from the system's home directory first.

  7. There may be cases where you need to modify the WEB-INF/login.conf file (in most cases you don't need to do this). In this case, too, it is best to move the file to the <plusworkflow.home>/config/kerberos/login.conf location to avoid storing it in the client project.
  8. Configure the browsers
    1. Mozilla Firefox
      1. type about:config in the address bar
      2. search for network.negotiate-auth.trusted-uris configuration
      3.  set as parameter value the path to the server on which PlusWorkflow is running, e.g. http://plusworkflow_test
    2. Internet Explorer
      1. add the system URL to trusted sites in Internet Options -> Security tab -> Trusted Sites
      2. check the Enable Windows Integrated Authentication option in Internet Options -> Advanced tab -> Security
      3. below Trusted Sites, click Custom Level and in the User Authentication section, check Log in automatically with the current username and current password
  9. Restart the system
  10. Test the operation of SSO
    1. log in to the computer in the domain using the account you previously added to the PlusWorkflow system
    2. delete all tickets from the system using the klist purge command
    3. log in to the system automatically by typing the system address in the browser bar (log in by server name, not address)

 

Troubleshooting

  1. Once properly configured and attempted to log in automatically, the klist command should display tickers similar to the following:


  2. Make sure that the case of the user's login in the domain controller is identical to the case of the user's login in the PW system.
  3. When checking the checkboxes in the username settings, change the password to another new one and re-enter it in the system (system parameters and LDAP if the same account defined there)
  4. Verify that the setspn command has been executed correctly on the AD server by executing (usually this must be done by the client since we do not have access to that server) a script in powershell:

    Skrypt Powershell
    $serviceType="HTTP"
    
    $spns = @{}
    
    $filter = "(servicePrincipalName=$serviceType/*)"
    $domain = New-Object System.DirectoryServices.DirectoryEntry
    $searcher = New-Object System.DirectoryServices.DirectorySearcher
    $searcher.SearchRoot = $domain
    $searcher.PageSize = 1000
    $searcher.Filter = $filter
    $results = $searcher.FindAll()
    
    
    foreach ($result in $results){
     $account = $result.GetDirectoryEntry()
     foreach ($spn in $account.servicePrincipalName.Value){
      if($spn.contains("$serviceType/")){
       $spns[$("$spn`t$($account.samAccountName)")]=1;
      }
     }
    }
    $spns.keys | sort-object

    The result of this script should be sent to us by the client. You should then check if there is a PlusWorkflow server with the indicated username in the list of spn records.

 

Related articles

There is no content with the specified labels

4 Comments

  1. Jeśli autologowanie nie działa lub przestało działać to proszę sprawdzić czy konto, które jest użyte w WEB-INF/web.xml do łączenia się z kontrolerem domeny jest aktywne.

    tzn.

    •  w systemie PlusWorkflow należy dodać nowego użytkownika z loginem użytym web.xml ( w tym przypadku należało by utworzyć użytkownika o loginie ="konto_ldap") i odpowiednią domeną jaka jest ustawione w konfiguracji LDAP w PlusWorkflow
      <init-param>
          <param-name>spnego.preauth.username</param-name>
          <param-value>konto_ldap</param-value>
      </init-param>
    • zalogować się na to konto do PlusWorkflow (zwykłe logowanie manualne w przeglądarce), uzyć hasło zapisane w web.xml ( w tym przypadku hasło to "haslo_ldap"
      <init-param>
          <param-name>spnego.preauth.password</param-name>
          <param-value>haslo_ldap</param-value>
      </init-param>
    • Jeśli nie można się zalogować to oznacza, że problem z kontem może występować na poziomie LDAP, system PlusWorkflow powinien przy probie zalogowania poinformować o typie błędu zwróconego z LDAP, ewentualnie w logach PlusWorkflow (Production.log) ldap powinien zwrócić kod informujący o statusie konta w LDAP.
      np. u jednego z klientów to konto zostało po nowym roku wyłączone w LDAP wyłączone i aby sprawdzić problem należało to zrobić jak jest opisane powyżej.

     

  2. Autologowanie w przeglądarce można sprawdzić korzystając z konta z WEB-INF/web.xml (konto zapisane w parametrach spnego.preauth.username i spnego.preauth.password).

    Wymagane jest spełnienie następujących warunków:

    • autologowanie nie możemy wykonać na serwerze do którego się łączymy (kwestia localhosta), tzn jeśli chcemy się połączyć do systemu produkcyjnego to najlepiej wykonać je na serwerze testowym
    • link autologowania musi być po domenie, nie po ip
    • jeśli korzystamy z konta WEB-INF/web.xml to należy dodać takiego użytkownika domenowego do PlusWorkflow, login taki jak wartość pola spnego.preauth.username  ,domena taka jak w ustawieniach ldap
    • przeglądarka skonfigurowana zgodnie z powyższym opisem (punkt 8)
    • wywoływany link do PlusWorkflow nie może być linkiem do manualnego logowania  "LoginManual.do", link powinien odnosić się do zwykłego logowania np.     "../PlusWorkflow/Login.do"

     

     

     

  3. Gdy wystąpi poniższy błąd, należy zweryfikować czas na serwerze PlusWorkflow i czas na serwerze Kerberos. Za pomocą komendy klist wyświetl tickety i sprawdź zwróconą godzinę. Powinna być zbliżona do godziny ustawionej na serwerze PlusWorkflow. Poniższy błąd wystąpił, gdy czasy różniły się o godzinę.

    Uwaga: Czas na serwerze najlepiej zmienić z linii komend poleceniem time.

    04-Feb-2020 14:03:33.552 SEVERE [http-nio-80-exec-7] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [action] in context with path [/PlusWorkflow] threw exception [GSSException: Failure unspecified at GSS-API level (Mechanism level: Clock skew too great (37))] with root cause
     KrbException: Clock skew too great (37)
        at sun.security.krb5.KrbApReq.authenticate(KrbApReq.java:302)
        at sun.security.krb5.KrbApReq.<init>(KrbApReq.java:149)
        at sun.security.jgss.krb5.InitSecContextToken.<init>(InitSecContextToken.java:108)
        at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:829)
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:342)
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285)
        at sun.security.jgss.spnego.SpNegoContext.GSS_acceptSecContext(SpNegoContext.java:906)
        at sun.security.jgss.spnego.SpNegoContext.acceptSecContext(SpNegoContext.java:556)
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:342)
        at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285)
        at net.sourceforge.spnego.SpnegoAuthenticator.doSpnegoAuth(SpnegoAuthenticator.java:445)
        at net.sourceforge.spnego.SpnegoAuthenticator.authenticate(SpnegoAuthenticator.java:272)
        at net.sourceforge.spnego.SpnegoHttpFilter.doFilter(SpnegoHttpFilter.java:253)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)
  4. Gdy wystąpi poniższy błąd, zweryfikuj konfigurację serwera domenowego w PlusWorkflow. Prawdopodobnie Domena SPNEGO jest nieprawidłowa. Po próbie automatycznego logowania użyj polecenia klist, aby wyświetlić tickety. W linii Server znajdziesz wymaganą domenę SPNEGO (przykład zaznaczono na poniższym zrzucie).

     

    13:37:15,886 http-nio-80-exec-3 UNKNOWN_USER 10.10.5.28 INFO AutoLogin:46  Uzytkownik ext_lizpaw rozpoznany poprzez protokol SPNEGO
    13:37:15,902 http-nio-80-exec-3   ERROR CharacterEncodingFilter:48  
    javax.servlet.ServletException: java.lang.NullPointerException
        at org.apache.struts.action.RequestProcessor.processException(RequestProcessor.java:545)
        at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:486)
        at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
        at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
        at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:507)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at com.suncode.pwfl.web.filter.UrlSecurityFilter.doFilter(UrlSecurityFilter.java:81)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.catalina.filters.HttpHeaderSecurityFilter.doFilter(HttpHeaderSecurityFilter.java:124)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at com.suncode.pwfl.audit.filter.AuditFilter.processManualAudit(AuditFilter.java:285)
        at com.suncode.pwfl.audit.filter.AuditFilter.doFilter(AuditFilter.java:80)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at com.plusmpm.filter.UserActivityServletFilter.doFilter(UserActivityServletFilter.java:50)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at com.suncode.pwfl.web.filter.UserRequestContextFilter.doFilterInternal(UserRequestContextFilter.java:70)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at com.plusmpm.filter.CacheResponseFilter.doFilter(CacheResponseFilter.java:43)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:125)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at com.plusmpm.filter.MDCUserActivityServletFilter.doFilter(MDCUserActivityServletFilter.java:76)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at com.plusmpm.filter.ActiveSessionFilter.doFilter(ActiveSessionFilter.java:133)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at com.suncode.pwfl.web.filter.DatabaseSetupFilter.doFilter(DatabaseSetupFilter.java:54)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at com.plusmpm.filter.CrossScriptingFilter.doFilter(CrossScriptingFilter.java:30)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at com.plusmpm.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:39)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at net.sourceforge.spnego.SpnegoHttpFilter.doFilter(SpnegoHttpFilter.java:277)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)
    Caused by: java.lang.NullPointerException
        at com.plusmpm.servlet.extension.AutoLogin.execute(AutoLogin.java:62)
        at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
        ... 68 more
    13:37:15,996 http-nio-80-exec-7   DEBUG ActiveSessionFilter:116  method: GET