Single sign-on
Single sign-on (Kerberos)
Kerberos is an authentication protocol. It is the default authentication protocol in Windows. The Single Sign-On (SSO) module integrates with Kerberos to let users to sign in to an HTTP application with Windows Active Directory credentials. Kerberos doesn’t typically go over HTTP, but an extension to the HTTP protocol, RFC 4559, adds a way to negotiate the protocol via the Www-Authenticate
and Authorization
HTTP headers. Then Kerberos tickets (identity tokens) are exchanged over the network by wrapping them inside Simple and Protected Negotiate (SPNEGO) tokens, defined by RFC 4178.
HAProxy Enterprise, being in front of the HTTP applications for which you want to enable single sign-on, validates the user’s Kerberos ticket and grants them access. Therefore, the applications themselves do not need to implement Kerberos directly.
To implement single sign-on using Kerberos, we will complete the following steps:
Configure Windows Server Jump to heading
In this section, you will configure Windows Server for Kerberos authentication.
Prerequisites Jump to heading
On Windows Server, please check that the following prerequisites have been met:
- You’ve installed the Active Directory Domain Services role.
- You’ve promoted the Windows Server instance to be a domain controller. A domain controller is a Windows Server where you administer Active Directory.
- You’ve created an Active Directory domain. In this guide, we will use the domain
example.com
. - You’ve installed the DNS Server role.
Create a user account and SPN Jump to heading
With Kerberos, every service gets a unique Service Principal Name (SPN). An SPN identifies a service running on a host. Because HAProxy Enterprise will act as a proxy in front of the applications, we will assign the SPNs to it. In Windows Server, we will create a user account in Active Directory to represent the load balancer and then assign to it an SPN for each load balanced web app. It might seem odd to assign a user account to a load balancer, but this is simply where we will map which services the load balancer can accept authorization requests for. By doing this, we are able to generate a keytab file, which we will store on the load balancer. When a user accesses the service via the load balancer, they present a ticket that the load balancer must decrypt with its keytab to prove that it is authorized by Active Directory.
-
Log in to your AD domain controller.
-
Open PowerShell and create a new user with the
New-ADUser
command. Note that the backtick is the word-wrap operator, allowing you to split the command onto multiple lines. Change the password used in the example:powershellNew-ADUser `-Name loadbalancer1 `-Description "Load balancer 1 service account" `-AccountPassword (ConvertTo-SecureString "P@ssword1" -AsPlainText -Force) `-PasswordNeverExpires $true `-KerberosEncryptionType AES256 `-Enabled $truepowershellNew-ADUser `-Name loadbalancer1 `-Description "Load balancer 1 service account" `-AccountPassword (ConvertTo-SecureString "P@ssword1" -AsPlainText -Force) `-PasswordNeverExpires $true `-KerberosEncryptionType AES256 `-Enabled $true -
Create a keytab file for the account by calling the
ktpass
command from PowerShell. The command does two things:- Maps the Service Principal Name
HTTP/webapp.example.com@EXAMPLE.COM
to the AD user accountexample\loadbalancer1
. The load balancer is then authorized to proxy requests for the servicewebapp.example.com
. - Generates a keytab file at
C:\loadbalancer1.keytab
, which contains the service’s key. After you’ve copied this file to the load balancer, the load balancer will be able to decrypt tickets.
powershellktpass /out C:\loadbalancer1.keytab /princ HTTP/webapp.example.com@EXAMPLE.COM /mapUser example\loadbalancer1 /crypto AES256-SHA1 /pType KRB5_NT_PRINCIPAL /pass +rndPasspowershellktpass /out C:\loadbalancer1.keytab /princ HTTP/webapp.example.com@EXAMPLE.COM /mapUser example\loadbalancer1 /crypto AES256-SHA1 /pType KRB5_NT_PRINCIPAL /pass +rndPassoutputtextTargeting domain controller: windowsserver.example.comUsing legacy password setting methodSuccessfully mapped HTTP/webapp.example.com to loadbalancer1.Key created.Output keytab to C:\loadbalancer1.keytabKeytab version: 0x502keysize 90 HTTP/webapp.example.com@EXAMPLE.COM ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x12 (AES256-SHA1) keylength 32outputtextTargeting domain controller: windowsserver.example.comUsing legacy password setting methodSuccessfully mapped HTTP/webapp.example.com to loadbalancer1.Key created.Output keytab to C:\loadbalancer1.keytabKeytab version: 0x502keysize 90 HTTP/webapp.example.com@EXAMPLE.COM ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x12 (AES256-SHA1) keylength 32In this example:
Field Description /out
The keytab to produce. /princ
The principal name (HTTP/FQDN@REALM). /mapUser
Maps the principal to the given user account. /crypto
The cryptosystem to use. AES256-SHA1
meansAES256-CTS-HMAC-SHA1-96
./pType
The principal type. KRB5_NT_PRINCIPAL
is the general, recommended ptype./pass
Sets the password. +rndPass
Generates a random password. View the Service Principal Name
To view a user account’s Service Principal Name:
- Open Server Manager and go to Tools > Active Directory Users and Computers.
- In the Active Directory Users and Computers window, open the View menu and enable Advanced Features.
- Expand your domain, select Users, and then double-click the user to view its properties. In our example, we created a user named
loadbalancer1
. - On the user’s properties, select the Attribute Editor tab.
- Scroll to the servicePrincipalName to see its value. In our example, the value is
HTTP/webapp.example.com
.
- Maps the Service Principal Name
Add a DNS record Jump to heading
Add a DNS record for your web app, pointed at your load balancer.
-
On your AD domain controller, go to Server Manager > Tools > DNS.
-
Expand Forward Lookup Zones in the tree, right-click on your domain (for example,
example.com
) and select New Host (A or AAAA). -
On the New Host dialog, set the name. For example,
webapp
. -
Set the IP address. For example, use your load balancer’s IP address.
-
Click Add Host.
You should see a dialog that says “The host record was successfully created”.
Optional: Disable NTLM Jump to heading
By disabling NTLM altogether you can make your network safer and eliminate the chance that the user’s browser and Windows Server will try to use it.
NTLM is an older and less secure protocol than Kerberos that runs in some Windows Active Directory domains. To authenticate with Kerberos over HTTP, the user’s web browser will exchange a series of messages with Windows Server to negotiate which authentication protocol to use. This is how the Www-Authenticate: Negotiate
HTTP header works. Though after this negotiation, the client and server may try to use NTLM instead of Kerberos.
If you see the following error in the SSO debug logs, then try disabling NTLM:
GSS-API error gss_accept_sec_context: An unsupported mechanism was requested
To disable NTLM:
- On your AD domain controller, go to Server Manager > Tools > Group Policy Management.
- Expand your forest and the domains folder in the Group Policy Management tree.
- If you do not yet have a group policy object, right-click on your domain and choose Create a GPO in this domain, and Link it here. Assign the new GPO a name.
- Expand your domain, right-click your new policy object, and choose Edit. The Group Policy Management Editor appears.
- Under Computer Configuration > Policies > Windows Settings > Security Settings > Local Policies > Security Options, double click the setting named Network security: Restrict NTLM: NTLM authentication in this domain. Set its value to
Disable
. - Optional: To speed up propagation of the new setting, on the target PC joined to the domain run PowerShell as an administrator and execute the command
gpupdate /force
.
Configure HAProxy Enterprise Jump to heading
In this section, you will configure HAProxy Enterprise for Kerberos authentication.
Install and configure the module Jump to heading
-
Install the SSO module according to your platform:
nixsudo apt-get install hapee-extras-spoa-ssonixsudo apt-get install hapee-extras-spoa-ssonixsudo yum install hapee-extras-spoa-ssonixsudo yum install hapee-extras-spoa-ssonixsudo zypper install hapee-extras-spoa-ssonixsudo zypper install hapee-extras-spoa-ssonixsudo pkg install hapee-extras-spoa-ssonixsudo pkg install hapee-extras-spoa-ssoIt installs the following files:
File Description /opt/hapee-extras/bin/hapee-krb-srv
Defines the SSO Kerberos service program. /etc/hapee-extras/hapee-krb-srv-spoe.cfg
Defines how the load balancer passes data via the Stream Processing Offload Protocol to the SSO Kerberos service. Typically, you will not need to edit this file. /etc/hapee-extras/hapee-krb-srv.cfg
Gives an example portion of an HAProxy Enterprise load balancer configuration that you can copy-paste. /etc/hapee-extras/hapee-sso-spoe.cfg
Not used in this setup. /etc/hapee-extras/hapee-sso.cfg
Not used in this setup. /etc/hapee-extras/sample/krb-srv.ini
Sets the location of your keytab file for each application. /etc/hapee-extras/sample/krb-srv.map
Maps HTTP Host
headers to applications./etc/hapee-extras/sample/sso.ini
Not used in this setup. /etc/hapee-extras/sample/sso.map
Not used in this setup. /etc/default/hapee-extras-sso
Defines the default settings for the hapee-extras-spoa-krb-srv
service. The file sets theKRBSRV_OPTIONS
environment variable. -
Copy the keytab file from Windows Server to the load balancer. For example, save it as
/etc/hapee-extras/keytabs/loadbalancer1.keytab
.nixsudo mkdir -p /etc/hapee-extras/keytabssudo cp ~/loadbalancer1.keytab /etc/hapee-extras/keytabs/nixsudo mkdir -p /etc/hapee-extras/keytabssudo cp ~/loadbalancer1.keytab /etc/hapee-extras/keytabs/ -
Copy the files
krb-srv.ini
andkrb-srv.map
from thesample
directory to/etc/hapee-extras
:nixsudo cp /etc/hapee-extras/sample/krb-srv.* /etc/hapee-extras/nixsudo cp /etc/hapee-extras/sample/krb-srv.* /etc/hapee-extras/ -
Edit
/etc/hapee-extras/krb-srv.ini
. Add adomain
section for your application and set the path to the keytab file. Also add an application section that references the domain section.krb-srv.iniini[domain:webapp.example.com]krb_keytab_file = /etc/hapee-extras/keytabs/loadbalancer1.keytab[webapp]domain = webapp.example.comkrb-srv.iniini[domain:webapp.example.com]krb_keytab_file = /etc/hapee-extras/keytabs/loadbalancer1.keytab[webapp]domain = webapp.example.com -
Edit
/etc/hapee-extras/krb-srv.map
. Add a line that maps the HTTPHost
header that you expect with the domain and app.krb-srv.maptext# Host header # doman / appwebapp.example.com webapp.example.com/webappkrb-srv.maptext# Host header # doman / appwebapp.example.com webapp.example.com/webapp -
Edit your main load balancer configuration file,
/etc/hapee-2.9/hapee-lb.cfg
.-
Add the
HA_SSO_SCOPE
variable to theglobal
section:haproxyglobalsetenv HA_SSO_SCOPE "sess"haproxyglobalsetenv HA_SSO_SCOPE "sess" -
Add the SSO Kerberos lines to the
frontend
for which you want to enable single sign-on:hapee-lb.cfghaproxyfrontend wwwbind :80default_backend servers#--------------------------------# SSO Kerberos section#--------------------------------option http-buffer-requestfilter spoe engine spoe_krb_srv config /etc/hapee-extras/hapee-krb-srv-spoe.cfg# HTTP REQUEST# set sso_app and sso_domain variables before calling the SPOAhttp-request set-var(txn.sso_domain) req.hdr(Host),map(/etc/hapee-extras/krb-srv.map),word(1,'/')http-request set-var(txn.sso_app) req.hdr(Host),map(/etc/hapee-extras/krb-srv.map),word(2,'/')# set sess.sso_cookie variable with the cookie set by the browserhttp-request set-var(txn.sso_cookie) req.cook(sso_cookie) if { req.cook(sso_cookie) -m found }# The authorization header might be sent on the first request of a session,# depending on the value set in "HA_SSO_SCOPE" variable we could accept a request if# a previous request was allowed in the current session.http-request return status 401 hdr www-authenticate Negotiate unless { var("$HA_SSO_SCOPE.sso.action") -m found } || { req.hdr(authorization) -m found }http-request send-spoe-group spoe_krb_srv grp-sso-check-tokenhttp-request deny if { var("$HA_SSO_SCOPE.sso.action") -m str dny }http-request deny if ! { var("$HA_SSO_SCOPE.sso.action") -m str alw }# The agent can extract a display name from a validated Kerberos tokenhttp-request del-header X-SSO-LOGINhttp-request set-header X-SSO-LOGIN %[var("$HA_SSO_SCOPE.sso.sso_login")] if { var("$HA_SSO_SCOPE.sso.sso_login") -m found }# If the SPOA has set "$HA_SSO_SCOPE.sso.www_authenticate" or "$HA_SSO_SCOPE.sso.sso_set_cookie" variables, we set the header accordinglyhttp-response add-header Set-Cookie sso_cookie=%[var("$HA_SSO_SCOPE.sso.sso_set_cookie")];\ path=/;\ domain=%[var("$HA_SSO_SCOPE.sso.sso_set_cookie_domain")]; if { var ("$HA_SSO_SCOPE.sso.sso_set_cookie") -m found }http-response add-header www-authenticate %[var("$HA_SSO_SCOPE.sso.www_authenticate")] if { var("$HA_SSO_SCOPE.sso.www_authenticate") -m found }# BACKENDSdefault_backend sso_erruse_backend sso_err if { var("$HA_SSO_SCOPE.sso.action") -m str err } # we got an error from the SPOAuse_backend %[var("$HA_SSO_SCOPE.sso.backend")] if { var("$HA_SSO_SCOPE.sso.action") -m str alw } { var("$HA_SSO_SCOPE.sso.backend") -m found }hapee-lb.cfghaproxyfrontend wwwbind :80default_backend servers#--------------------------------# SSO Kerberos section#--------------------------------option http-buffer-requestfilter spoe engine spoe_krb_srv config /etc/hapee-extras/hapee-krb-srv-spoe.cfg# HTTP REQUEST# set sso_app and sso_domain variables before calling the SPOAhttp-request set-var(txn.sso_domain) req.hdr(Host),map(/etc/hapee-extras/krb-srv.map),word(1,'/')http-request set-var(txn.sso_app) req.hdr(Host),map(/etc/hapee-extras/krb-srv.map),word(2,'/')# set sess.sso_cookie variable with the cookie set by the browserhttp-request set-var(txn.sso_cookie) req.cook(sso_cookie) if { req.cook(sso_cookie) -m found }# The authorization header might be sent on the first request of a session,# depending on the value set in "HA_SSO_SCOPE" variable we could accept a request if# a previous request was allowed in the current session.http-request return status 401 hdr www-authenticate Negotiate unless { var("$HA_SSO_SCOPE.sso.action") -m found } || { req.hdr(authorization) -m found }http-request send-spoe-group spoe_krb_srv grp-sso-check-tokenhttp-request deny if { var("$HA_SSO_SCOPE.sso.action") -m str dny }http-request deny if ! { var("$HA_SSO_SCOPE.sso.action") -m str alw }# The agent can extract a display name from a validated Kerberos tokenhttp-request del-header X-SSO-LOGINhttp-request set-header X-SSO-LOGIN %[var("$HA_SSO_SCOPE.sso.sso_login")] if { var("$HA_SSO_SCOPE.sso.sso_login") -m found }# If the SPOA has set "$HA_SSO_SCOPE.sso.www_authenticate" or "$HA_SSO_SCOPE.sso.sso_set_cookie" variables, we set the header accordinglyhttp-response add-header Set-Cookie sso_cookie=%[var("$HA_SSO_SCOPE.sso.sso_set_cookie")];\ path=/;\ domain=%[var("$HA_SSO_SCOPE.sso.sso_set_cookie_domain")]; if { var ("$HA_SSO_SCOPE.sso.sso_set_cookie") -m found }http-response add-header www-authenticate %[var("$HA_SSO_SCOPE.sso.www_authenticate")] if { var("$HA_SSO_SCOPE.sso.www_authenticate") -m found }# BACKENDSdefault_backend sso_erruse_backend sso_err if { var("$HA_SSO_SCOPE.sso.action") -m str err } # we got an error from the SPOAuse_backend %[var("$HA_SSO_SCOPE.sso.backend")] if { var("$HA_SSO_SCOPE.sso.action") -m str alw } { var("$HA_SSO_SCOPE.sso.backend") -m found } -
Ensure that the name of the
backend
for your application matches the name of the application section inkrb-srv.ini
. In our example,krb-srv.ini
contained[webapp]
, so we would name the backendwebapp
:hapee-lb.cfghaproxybackend webappbalance roundrobinserver web1 127.0.0.1:3000 checkhapee-lb.cfghaproxybackend webappbalance roundrobinserver web1 127.0.0.1:3000 check -
Add the following two
backend
sections:hapee-lb.cfghaproxybackend sso_errmode httpbackend spoa-backendmode tcptimeout server 1mserver sso-daemon 127.0.0.1:12345 inter 1s checkhapee-lb.cfghaproxybackend sso_errmode httpbackend spoa-backendmode tcptimeout server 1mserver sso-daemon 127.0.0.1:12345 inter 1s check
-
-
Reload the load balancer:
nixsudo systemctl reload hapee-2.9-lbnixsudo systemctl reload hapee-2.9-lb -
Enable and start the service:
nixsudo systemctl enable hapee-extras-spoa-krb-srvsudo systemctl start hapee-extras-spoa-krb-srvnixsudo systemctl enable hapee-extras-spoa-krb-srvsudo systemctl start hapee-extras-spoa-krb-srv -
The service’s status should indicate that it is now configured for the new application.
nixsudo systemctl status hapee-extras-spoa-krb-srvnixsudo systemctl status hapee-extras-spoa-krb-srvoutputtexthapee systemd[1]: Starting hapee-extras-spoa-krb-srv.service - HAPEE SPOA-KRB-SRV: HAPEE SSO solution...hapee hapee-krb-srv[4955]: [00] Configured domains:hapee hapee-krb-srv[4955]: 1713465556.954921 [00] Configured domains:hapee hapee-krb-srv[4955]: 1713465556.954951 [00] domain:webapp.example.com (1 app)hapee hapee-krb-srv[4955]: [00] domain:webapp.example.com (1 app)hapee hapee-krb-srv[4956]: 1713465556.956454 [00] SSO Server will start in background, pid=4956hapee hapee-krb-srv[4956]: [00] SSO Server will start in background, pid=4956hapee systemd[1]: Started hapee-extras-spoa-krb-srv.service - HAPEE SPOA-KRB-SRV: HAPEE SSO solution.hapee HAProxy-sso[4956]: [00] SSO server is ready and listening on port 12345outputtexthapee systemd[1]: Starting hapee-extras-spoa-krb-srv.service - HAPEE SPOA-KRB-SRV: HAPEE SSO solution...hapee hapee-krb-srv[4955]: [00] Configured domains:hapee hapee-krb-srv[4955]: 1713465556.954921 [00] Configured domains:hapee hapee-krb-srv[4955]: 1713465556.954951 [00] domain:webapp.example.com (1 app)hapee hapee-krb-srv[4955]: [00] domain:webapp.example.com (1 app)hapee hapee-krb-srv[4956]: 1713465556.956454 [00] SSO Server will start in background, pid=4956hapee hapee-krb-srv[4956]: [00] SSO Server will start in background, pid=4956hapee systemd[1]: Started hapee-extras-spoa-krb-srv.service - HAPEE SPOA-KRB-SRV: HAPEE SSO solution.hapee HAProxy-sso[4956]: [00] SSO server is ready and listening on port 12345
Optional: Add a second application Jump to heading
To add another application to SSO:
-
On your Windows Server, add a DNS record for the new application.
- On your AD domain controller, go to Server Manager > Tools > DNS.
- Expand Forward Lookup Zones in the tree, right-click on your domain (for example,
example.com
) and select New Host (A or AAAA). - On the New Host dialog, set the name. For example,
webapp2
. - Set the IP address. For example, use your load balancer’s IP address.
- Click Add Host.
-
To add more SPNs to the user account to support other web applications, use the
/in
argument when callingktpass
to append new SPNs:powershellktpass /in C:\loadbalancer1.keytab /out C:\loadbalancer1.keytab /princ HTTP/webapp2.example.com@EXAMPLE.COM /mapUser example\loadbalancer1 /crypto AES256-SHA1 /pType KRB5_NT_PRINCIPAL /pass +rndPasspowershellktpass /in C:\loadbalancer1.keytab /out C:\loadbalancer1.keytab /princ HTTP/webapp2.example.com@EXAMPLE.COM /mapUser example\loadbalancer1 /crypto AES256-SHA1 /pType KRB5_NT_PRINCIPAL /pass +rndPassoutputtextExisting keytab:keytab version: 0x502keysize 90 HTTP/webapp.example.com@EXAMPLE.COM pType 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x12 (AES256-SHA1) keylength 32Targeting domain controller: windowsserver.example.comUsing legacy password setting methodSuccessfully mapped HTTP/webapp2.example.com to loadbalancer1.Key created.Output keytab to C:\loadbalancer1.keytab:Keytab version: 0x502keysize 90 HTTP/webapp.example.com@EXAMPLE.COM ptype1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x12 (AES256-SHA1) keylength 32keysize 91 HTTP/webapp2.example.com@EXAMPLE.COM ptype1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x12 (AES256-SHA1) keylength 32outputtextExisting keytab:keytab version: 0x502keysize 90 HTTP/webapp.example.com@EXAMPLE.COM pType 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x12 (AES256-SHA1) keylength 32Targeting domain controller: windowsserver.example.comUsing legacy password setting methodSuccessfully mapped HTTP/webapp2.example.com to loadbalancer1.Key created.Output keytab to C:\loadbalancer1.keytab:Keytab version: 0x502keysize 90 HTTP/webapp.example.com@EXAMPLE.COM ptype1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x12 (AES256-SHA1) keylength 32keysize 91 HTTP/webapp2.example.com@EXAMPLE.COM ptype1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x12 (AES256-SHA1) keylength 32 -
Copy the keytab file to the load balancer.
-
Edit
/etc/hapee-extras/krb-srv.ini
. Add adomain
section for your application and set the path to the keytab file. Also add an application section that references the domain section.krb-srv.iniini[domain:webapp.example.com]krb_keytab_file = /etc/hapee-extras/keytabs/loadbalancer1.keytab[webapp]domain = webapp.example.com[domain:webapp2.example.com]krb_keytab_file = /etc/hapee-extras/keytabs/loadbalancer1.keytab[webapp2]domain = webapp2.example.comkrb-srv.iniini[domain:webapp.example.com]krb_keytab_file = /etc/hapee-extras/keytabs/loadbalancer1.keytab[webapp]domain = webapp.example.com[domain:webapp2.example.com]krb_keytab_file = /etc/hapee-extras/keytabs/loadbalancer1.keytab[webapp2]domain = webapp2.example.com -
Edit
/etc/hapee-extras/krb-srv.map
. Add a line that maps the HTTPHost
header that you expect with the domain and app.krb-srv.maptext# Host header # doman / appwebapp.example.com webapp.example.com/webappwebapp2.example.com webapp2.example.com/webapp2krb-srv.maptext# Host header # doman / appwebapp.example.com webapp.example.com/webappwebapp2.example.com webapp2.example.com/webapp2 -
Restart the SSO Kerberos service:
nixsudo systemctl restart hapee-extras-spoa-krb-srvnixsudo systemctl restart hapee-extras-spoa-krb-srvThe service’s status should indicate that it is now configured for the new application.
nixsudo systemctl status hapee-extras-spoa-krb-srvnixsudo systemctl status hapee-extras-spoa-krb-srvoutputtexthapee hapee-krb-srv[6283]: 1713397718.771858 [00] Configured domains:hapee hapee-krb-srv[6283]: 1713397718.771899 [00] domain:webapp.example.com (1 app)hapee hapee-krb-srv[6283]: 1713397718.771905 [00] domain:webapp2.example.com (1 app)outputtexthapee hapee-krb-srv[6283]: 1713397718.771858 [00] Configured domains:hapee hapee-krb-srv[6283]: 1713397718.771899 [00] domain:webapp.example.com (1 app)hapee hapee-krb-srv[6283]: 1713397718.771905 [00] domain:webapp2.example.com (1 app) -
Edit your main load balancer configuration file,
/etc/hapee-2.9/hapee-lb.cfg
. Ensure that the name of thebackend
for your application matches the name of the application section inkrb-srv.ini
. For example,webapp2
:hapee-lb.cfghaproxybackend webapp2balance roundrobinserver web1 127.0.0.1:3001 checkhapee-lb.cfghaproxybackend webapp2balance roundrobinserver web1 127.0.0.1:3001 check -
Reload the load balancer:
nixsudo systemctl reload hapee-2.9-lbnixsudo systemctl reload hapee-2.9-lb
Configure user PCs Jump to heading
In this section, you will configure users’ Windows PCs for Kerberos authentication.
Update DNS and AD settings Jump to heading
To allow single sign-on in the AD domain, update the user’s PC to use the domain’s DNS server and, optionally, join the computer to the domain.
-
Update the user’s preferred DNS server to point to Windows Server. That way, they can access internal subdomains like
webapp.example.com
. On the user’s PC:-
On the Desktop, click the Start button, type
Control Panel
, and then pressenter
. -
Navigate to Network and Internet, and then Network and Sharing Center.
-
Click Change adapter settings.
-
Right-click on your adapter (for example, Ethernet) and select Properties.
-
On the adapter’s Properties dialog, double-click Internet Protocol Version 4 (TCP/IPv4) to open the protocol’s properties.
-
Click Advanced, then select the DNS tab.
-
Under DNS server addresses, click Add, then enter the IP address of your Windows Server. Click Add.
-
Click OK to save the change.
-
To verify, open PowerShell and use
nslookup
to retrieve the IP address for your AD domain controller server. For example:powershellnslookup windowsserver.example.compowershellnslookup windowsserver.example.comoutputtextName: windowsserver.example.comAddresses: 192.168.56.60outputtextName: windowsserver.example.comAddresses: 192.168.56.60
-
When the user accesses the web application, for example webapp.example.com
, through their browser, they will see a login prompt. They can enter their Active Directory credentials.
Optional: Integrated authentication Jump to heading
To skip the login prompt and instead enable Microsoft Edge to use the credentials of the logged-in Windows user, enable integrated authentication. This allows the browser to use the credentials from the Windows operating system and skip being prompted. You will set this as a Group Policy so that it applies to all computers joined to the Active Directory domain.
- On the Active Directory domain controller, go to the Microsoft Edge website and click the link Download Windows 64-bit Policy to download the archive. Extract the contents of the archive.
- In Windows Explorer, navigate to the policies directory for your domain. For example, for the domain
example.com
, it would beC:\Windows\SYSVOL\sysvol\example.com\Policies
. From there, create a directory namedPolicyDefinitions
. - From the extracted archive, copy the contents of the
MicrosoftEdgePolicyTemplates\windows\admx
directory into the newPolicyDefinitions
directory. - Open Server Manager and go to Tools > Group Policy Management. Expand your forest and domain in the Group Policy Management tree.
- If you do not yet have a group policy object, right-click on your domain and choose Create a GPO in this domain, and Link it here. Assign the new GPO a name.
- Expand your domain, right-click your new policy object, and choose Edit. The Group Policy Management Editor appears.
- Under Computer Configuration > Policies > Administrative Templates, expand the new Microsoft Edge policy definition in the Group Policy Management Editor.
- Within HTTP Authentication, edit the setting named Configure list of allowed authentication servers, enable it, and set its value to your load balanced application. For example,
webapp.example.com
or*.example.com
. - Optional: If the setting Supported authentication schemes has been configured, then be sure its value includes
negotiate
.
To verify that the policy has been rolled out:
- On the user’s PC, run PowerShell and execute
gpupdate /force
. - Open Microsoft Edge and go to
edge://policy
to see the applied policies. You should see the policy namedAuthServerAllowlist
set to your target hostname.
Troubleshooting Jump to heading
This section describes how to troubleshoot the SSO Kerberos service.
Validate the configuration Jump to heading
To validate your configuration file:
-
Call
hapee-krb-srv
with the--check-cfg
flag:nix/opt/hapee-extras/bin/hapee-krb-srv -f /etc/hapee-extras/krb-srv.ini --check-cfgnix/opt/hapee-extras/bin/hapee-krb-srv -f /etc/hapee-extras/krb-srv.ini --check-cfgoutputtext1713906912.716699 [00] Configured domains:1713906912.717762 [00] domain:webapp.example.com (1 app)1713906912.717880 [00] Configuration parsed successfully.1713906912.717897 [00] Exitingoutputtext1713906912.716699 [00] Configured domains:1713906912.717762 [00] domain:webapp.example.com (1 app)1713906912.717880 [00] Configuration parsed successfully.1713906912.717897 [00] Exiting
Debug logs Jump to heading
The SSO module has startup flags that enable debug-level logs, which can help when diagnosing problems.
-
Edit the file
/etc/default/hapee-extras-sso
and change theKRBSRV_OPTIONS
line so that it includes one of the following debug flags:Flag Description --debug-spoe
Shows information and events about the Stream Processing Offload Engine (SPOE), which is how the load balancer communicates with the SSO Kerberos service. --debug-spoe-variables
Shows the SPOE variables that the load balancer passes to the SSO Kerberos service. --debug-sso
Shows messages about the single sign-on flow, such as whether a client authenticated successfully. --debug-krb
Show messages related to the load balancer processing the Kerberos protocol. Additional details are saved to a log file in the /tmp
directory.--debug-krb-err
Shows errors that occur while processing the Kerberos protocol. --debug-all
Enables all debugging flags. -
Restart the SSO Kerberos service:
nixsudo systemctl restart hapee-extras-spoa-krb-srvnixsudo systemctl restart hapee-extras-spoa-krb-srv
In the following sections, we show examples.
debug-spoe Jump to heading
Show information and events about the Stream Processing Offload Engine (SPOE), which is how the load balancer communicates with the SSO Kerberos service.
hapee-extras-ssotext
KRBSRV_OPTIONS="--uid hapee-sso --gid hapee --debug-spoe"
hapee-extras-ssotext
KRBSRV_OPTIONS="--uid hapee-sso --gid hapee --debug-spoe"
Use journalctl
to show logs:
nix
sudo journalctl --follow --unit hapee-extras-spoa-krb-srv
nix
sudo journalctl --follow --unit hapee-extras-spoa-krb-srv
outputtext
Apr 23 19:09:14 hapee HAProxy-sso[1118]: [00] <1> New Client connection accepted and assigned to worker 01Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> read_frame_cbApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> New Frame of 129 bytes receivedApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Decode HAProxy HELLO frameApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Supported versions : 2.0Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> HAProxy maximum frame size : 16380Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> HAProxy capabilities : pipelining,asyncApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> HAProxy supports frame pipeliningApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> HAProxy supports asynchronous frameApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> HAProxy engine id : 6fb22acf-84a8-47b2-bece-bfb60a8aa88aApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Encode Agent HELLO frameApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Agent version : 2.0Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Agent maximum frame size : 16380Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Agent capabilities :Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> write_frame_cbApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Frame of 54 bytes sentApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> read_frame_cbApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> New Frame of 2486 bytes receivedApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Decode HAProxy NOTIFY frameApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> STREAM-ID=10 - FRAME-ID=1 - unfragmented frame received - frag_len=0 - len=2486 - offset=7Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] Process frame messages : STREAM-ID=10 - FRAME-ID=1 - length=2479 bytesApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] Encode Agent ACK frameApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] STREAM-ID=10 - FRAME-ID=1Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> write_frame_cbApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Frame of 601 bytes sent
outputtext
Apr 23 19:09:14 hapee HAProxy-sso[1118]: [00] <1> New Client connection accepted and assigned to worker 01Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> read_frame_cbApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> New Frame of 129 bytes receivedApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Decode HAProxy HELLO frameApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Supported versions : 2.0Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> HAProxy maximum frame size : 16380Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> HAProxy capabilities : pipelining,asyncApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> HAProxy supports frame pipeliningApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> HAProxy supports asynchronous frameApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> HAProxy engine id : 6fb22acf-84a8-47b2-bece-bfb60a8aa88aApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Encode Agent HELLO frameApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Agent version : 2.0Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Agent maximum frame size : 16380Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Agent capabilities :Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> write_frame_cbApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Frame of 54 bytes sentApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> read_frame_cbApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> New Frame of 2486 bytes receivedApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Decode HAProxy NOTIFY frameApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> STREAM-ID=10 - FRAME-ID=1 - unfragmented frame received - frag_len=0 - len=2486 - offset=7Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] Process frame messages : STREAM-ID=10 - FRAME-ID=1 - length=2479 bytesApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] Encode Agent ACK frameApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] STREAM-ID=10 - FRAME-ID=1Apr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> write_frame_cbApr 23 19:09:14 hapee HAProxy-sso[1118]: [01] <1> Frame of 601 bytes sent
debug-spoe-variables Jump to heading
Show the SPOE variables that the load balancer passes to the SSO Kerberos service.
hapee-extras-ssotext
KRBSRV_OPTIONS="--uid hapee-sso --gid hapee --debug-spoe-variables"
hapee-extras-ssotext
KRBSRV_OPTIONS="--uid hapee-sso --gid hapee --debug-spoe-variables"
Use journalctl
to show logs:
nix
sudo journalctl --follow --unit hapee-extras-spoa-krb-srv
nix
sudo journalctl --follow --unit hapee-extras-spoa-krb-srv
outputtext
Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] SPOA argument: sso_app, size=6Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] SPOA argument: sso_domain, size=20Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] SPOA argument: sso_cookie, size=32Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] SPOA argument: method, size=3Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] SPOA argument: authorization, size=2338Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] ==> SPOE sso-check-token message: sso_domain=webapp.example.com sso_app=webapp sso_cookie=8a1200062d3b7222432f00b47ca051dd authorization=Negotiate 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 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=1 sso_set_cookie=2a9dd981820179a19cf5b8d4bae0862b; HttpOnly; Expires=Wed, 24 Apr 2024 05:14:48 GMTApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=1 sso_set_cookie_domain=Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=1 sso_cookie=2a9dd981820179a19cf5b8d4bae0862bApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=2 backend=webappApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=2 sso_app=webappApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=2 sso_domain=webapp.example.comApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=2 www_authenticate=Negotiate oYG1MIGyoAMKAQChCwYJKoZIgvcSAQICooGdBIGaYIGXBgkqhkiG9xIBAgICAG+BhzCBhKADAgEFoQMCAQ+ieDB2oAMCARKibwRtIZy7J4L1xwE98XQeAjHPqDg1V2qWDMvIyhh3x8abTBbgV9l8b69nm9XQ+3a0iVxDWB0Wuzdrm14ff2SeAmRI3WRcWVApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=2 sso_login=myuser@example.comApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=2 action=alwApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var int scope=2 status=0
outputtext
Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] SPOA argument: sso_app, size=6Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] SPOA argument: sso_domain, size=20Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] SPOA argument: sso_cookie, size=32Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] SPOA argument: method, size=3Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] SPOA argument: authorization, size=2338Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] ==> SPOE sso-check-token message: sso_domain=webapp.example.com sso_app=webapp sso_cookie=8a1200062d3b7222432f00b47ca051dd authorization=Negotiate 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 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=1 sso_set_cookie=2a9dd981820179a19cf5b8d4bae0862b; HttpOnly; Expires=Wed, 24 Apr 2024 05:14:48 GMTApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=1 sso_set_cookie_domain=Apr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=1 sso_cookie=2a9dd981820179a19cf5b8d4bae0862bApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=2 backend=webappApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=2 sso_app=webappApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=2 sso_domain=webapp.example.comApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=2 www_authenticate=Negotiate oYG1MIGyoAMKAQChCwYJKoZIgvcSAQICooGdBIGaYIGXBgkqhkiG9xIBAgICAG+BhzCBhKADAgEFoQMCAQ+ieDB2oAMCARKibwRtIZy7J4L1xwE98XQeAjHPqDg1V2qWDMvIyhh3x8abTBbgV9l8b69nm9XQ+3a0iVxDWB0Wuzdrm14ff2SeAmRI3WRcWVApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=2 sso_login=myuser@example.comApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var str scope=2 action=alwApr 23 19:14:48 hapee HAProxy-sso[1151]: [01] Encode SPOE set-var int scope=2 status=0
debug-sso Jump to heading
Show messages about the single sign-on flow, such as whether a client authenticated successfully.
hapee-extras-ssotext
KRBSRV_OPTIONS="--uid hapee-sso --gid hapee --debug-sso"
hapee-extras-ssotext
KRBSRV_OPTIONS="--uid hapee-sso --gid hapee --debug-sso"
Use journalctl
to show logs:
nix
sudo journalctl --follow --unit hapee-extras-spoa-krb-srv
nix
sudo journalctl --follow --unit hapee-extras-spoa-krb-srv
outputtext
Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Process SPOE Message 'sso-check-token'Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] ==> Process SPOE Message 'sso-check-token' with 5 args. len left: 2462Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] ==> SPOE sso-check-token messageApr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Unexpected SPOA argument: methodApr 23 19:17:57 hapee HAProxy-sso[1177]: [00] Cleaning cookie contexts that have expired...Apr 23 19:17:57 hapee HAProxy-sso[1177]: [00] Purged 0/0 cookie contextsApr 23 19:17:57 hapee HAProxy-sso[1177]: [01] In handle_authorization()Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Generating a new sso cookie...Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Created new cookie 23dfd3e13b171bc5310bb885db30e0e1Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Adding new domain context for domain webapp.example.com for cookie 23dfd3e13b171bc5310bb885db30e0e1. Expires=2024-04-24 05:17:57Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Storing SSO cookie 23dfd3e13b171bc5310bb885db30e0e1, expires on 2024-04-24 05:17:57Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] AUTH_RESULT=SUCCESSApr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Setting action to SSO_ACTION_ALLOWApr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Next action=alw msg=(null)Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] ======================= response frame encoded, 594 bytes
outputtext
Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Process SPOE Message 'sso-check-token'Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] ==> Process SPOE Message 'sso-check-token' with 5 args. len left: 2462Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] ==> SPOE sso-check-token messageApr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Unexpected SPOA argument: methodApr 23 19:17:57 hapee HAProxy-sso[1177]: [00] Cleaning cookie contexts that have expired...Apr 23 19:17:57 hapee HAProxy-sso[1177]: [00] Purged 0/0 cookie contextsApr 23 19:17:57 hapee HAProxy-sso[1177]: [01] In handle_authorization()Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Generating a new sso cookie...Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Created new cookie 23dfd3e13b171bc5310bb885db30e0e1Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Adding new domain context for domain webapp.example.com for cookie 23dfd3e13b171bc5310bb885db30e0e1. Expires=2024-04-24 05:17:57Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Storing SSO cookie 23dfd3e13b171bc5310bb885db30e0e1, expires on 2024-04-24 05:17:57Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] AUTH_RESULT=SUCCESSApr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Setting action to SSO_ACTION_ALLOWApr 23 19:17:57 hapee HAProxy-sso[1177]: [01] Next action=alw msg=(null)Apr 23 19:17:57 hapee HAProxy-sso[1177]: [01] ======================= response frame encoded, 594 bytes
debug-krb Jump to heading
Show messages related to the load balancer processing the Kerberos protocol. Additional details are saved to a log file in the /tmp
directory. In the example below, the log file is named /tmp/krb_debug_webapp.example.com.log
.
hapee-extras-ssotext
KRBSRV_OPTIONS="--uid hapee-sso --gid hapee --debug-krb"
hapee-extras-ssotext
KRBSRV_OPTIONS="--uid hapee-sso --gid hapee --debug-krb"
Use journalctl
to show logs:
nix
sudo journalctl --follow --unit hapee-extras-spoa-krb-srv
nix
sudo journalctl --follow --unit hapee-extras-spoa-krb-srv
outputtext
Apr 23 19:19:43 hapee HAProxy-sso[1207]: [00] Logging Kerberos operations to /tmp/krb_debug_webapp.example.com.logApr 23 19:19:43 hapee HAProxy-sso[1207]: [00] Token validated for client "myuser@example.com"
outputtext
Apr 23 19:19:43 hapee HAProxy-sso[1207]: [00] Logging Kerberos operations to /tmp/krb_debug_webapp.example.com.logApr 23 19:19:43 hapee HAProxy-sso[1207]: [00] Token validated for client "myuser@example.com"
Then the file krb_debug_webapp.example.com.log
in the /tmp
directory contains additional details:
krb_debug_webapp.example.com.logtext
[1207] 1713899983.885398: Decrypted AP-REQ with server principal HTTP/webapp.example.com@EXAMPLE.COM: aes256-cts/5511[1207] 1713899983.885399: AP-REQ ticket: myuser@EXAMPLE.COM -> HTTP/webapp.example.com@EXAMPLE.COM, session key aes256-cts/C099[1207] 1713899983.885400: Negotiated enctype based on authenticator: aes256-cts[1207] 1713899983.885401: Authenticator contains subkey: aes256-cts/A116[1207] 1713899983.885402: Creating AP-REP, time 1713899983.12, subkey aes256-cts/D7DE, seqnum 255461910[1257] 1713900224.105711: Decrypted AP-REQ with server principal HTTP/webapp.example.com@EXAMPLE.COM: aes256-cts/5511[1257] 1713900224.105712: AP-REQ ticket: myuser@EXAMPLE.COM -> HTTP/webapp.example.com@EXAMPLE.COM, session key aes256-cts/D0FA[1257] 1713900224.105713: Negotiated enctype based on authenticator: aes256-cts[1257] 1713900224.105714: Authenticator contains subkey: aes256-cts/03DC[1257] 1713900224.105715: Creating AP-REP, time 1713900223.18, subkey aes256-cts/9481, seqnum 1008188495
krb_debug_webapp.example.com.logtext
[1207] 1713899983.885398: Decrypted AP-REQ with server principal HTTP/webapp.example.com@EXAMPLE.COM: aes256-cts/5511[1207] 1713899983.885399: AP-REQ ticket: myuser@EXAMPLE.COM -> HTTP/webapp.example.com@EXAMPLE.COM, session key aes256-cts/C099[1207] 1713899983.885400: Negotiated enctype based on authenticator: aes256-cts[1207] 1713899983.885401: Authenticator contains subkey: aes256-cts/A116[1207] 1713899983.885402: Creating AP-REP, time 1713899983.12, subkey aes256-cts/D7DE, seqnum 255461910[1257] 1713900224.105711: Decrypted AP-REQ with server principal HTTP/webapp.example.com@EXAMPLE.COM: aes256-cts/5511[1257] 1713900224.105712: AP-REQ ticket: myuser@EXAMPLE.COM -> HTTP/webapp.example.com@EXAMPLE.COM, session key aes256-cts/D0FA[1257] 1713900224.105713: Negotiated enctype based on authenticator: aes256-cts[1257] 1713900224.105714: Authenticator contains subkey: aes256-cts/03DC[1257] 1713900224.105715: Creating AP-REP, time 1713900223.18, subkey aes256-cts/9481, seqnum 1008188495
Do you have any suggestions on how we can improve the content of this page?