Description
Motivation
When using Gitea on premises in a Windows environment (with Active Directory), it would be very convenient to be able to use single sign-on authentication via Kerberos. Currently Gitea supports LDAP authentication to Active Directory (https://docs.gitea.io/en-us/authentication/), but LDAP is not single sign-on.
Short overview of proposal
The proposal is to support Single single-on authentication with Kerberos by implementing the protocol defined by RFC4559 (SPNEGO-based HTTP Authentication in Microsoft Windows) to exchange authentication data between the web browser and HTTP server, and the Security Support Provider Interface (SSPI) to perform the authentication.
Use cases
-
When installing Gitea:
-
When opening the home page:
- If the user follows any link on the home page (eg. the
Register
orSign In
buttons) authentication is performed and the user is automatically signed in with the Kerberos credentials he is currently using in the operating system.
- If the user follows any link on the home page (eg. the
-
When SSPI authentication is enabled, but the user needs to temporary use another authentication method (eg. to login as local user with administrative rights):
- The dashboard for anonymous users contains an additional button for temporary disabling single sing-on (the button
Disable Single Sign-On
appears only if SSPI authentication has been enabled in configuration):
- The menu for users that are already signed in with SSO also have an option to temporary disable SSO:
- The dashboard for anonymous users contains an additional button for temporary disabling single sing-on (the button
-
The user finished his work as local user and wants to use single-sign on again (to login as the user currently signed in the operating system):
Configuration
The [service]
section of the app.ini
could contain the following additional options:
; Enable SPNEGO authentication via the built-in SSPI module in Windows.
; To use SSPI authentication you need to create suitable service principal name (SPN)
; for the user running gitea (see https://github.com/quasoft/websspi for more details)
ENABLE_SSPI = false
; Allow SSPI auth method to automatically create new users on the go
SSPI_AUTO_CREATE_USERS = true
; Allow SSPI auth method to automatically activate new users
SSPI_AUTO_ACTIVATE_USERS = true
; The character to use to replace the separators of down-level logon names (eg. the \
; in "DOMAIN\user") and user principal names (eg. the @ in "[email protected]")
SSPI_SEPARATOR_REPLACEMENT = _
; Default language for users automatically created by SSPI auth method
SSPI_DEFAULT_LANG = en-us
Those additional configuration values could be displayed in the Service configuration
section of /admin/config
page:
Design
Why SSPI and not a cross-platform kerberos library?
SSPI is chosen for verification because in Windows only environments (where both the client and server run Windows) it works without keytab files, which simplifies setup and improves security by not forcing you to store the user password in a keytab file.
How will this new authentication method be integrated into Gitea codebase?
The SignedInUser function of the auth
module (https://github.com/go-gitea/gitea/blob/master/modules/auth/auth.go) is already doing authentication at the middleware level for:
- Reverse proxy authentication via the
X-WEBAUTH-USER
header:Line 134 in 46a12f1
- Basic authentication with the
Authorization
header:Line 172 in 46a12f1
- OAuth authentication with the
Authorization
header or with thetoken
andaccess_token
query params:Line 44 in 46a12f1
Line 189 in 46a12f1
SSPI authentication could be added to the same SignedInUser function, but that would increase the compexity of the file.
A better approach could be to introduce something like a plugin pattern for Single single sign-on authentication methods. A separate subpackage modules/auth/sso
could be created with a common interface:
// SingleSignOn represents a SSO authentication method (plugin) for HTTP requests.
type SingleSignOn interface {
// Init should be called exactly once before using any of the other methods,
// in order to allow the plugin to allocate necessary resources
Init() error
// Free should be called exactly once before application closes, in order to
// give chance to the plugin to free any allocated resources
Free() error
// IsEnabled checks if the current SSO method has been enabled in settings.
IsEnabled() bool
// VerifyAuthData tries to verify the SSO authentication data contained in the request.
// If verification is successful returns either an existing user object (with id > 0)
// or a new user object (with id = 0) populated with the information that was found
// in the authentication data (username or email).
// Returns nil if verification fails.
VerifyAuthData(ctx *macaron.Context) *models.User
}
Specific implementations of that interface could be:
basic.go
oauth2.go
reverseproxy.go
sspi_windows.go
Basic, OAuth and Reverse proxy authentication will be moved from the modules/auth/auth.go
file to those "plugin" implementations.
A new plugin implementing the interface will be introduced for SSPI authentication.
Authentication plugins would be used at the middleware level - inside the same SignedInUser function:
// Try to sign in with each of the enabled plugins
for _, ssoMethod := range sso.Methods() {
if !ssoMethod.IsEnabled() {
continue
}
user = ssoMethod.VerifyAuthData(ctx)
if user != nil {
handleSignIn(ctx, sess, user)
_, isBasic := ssoMethod.(*sso.Basic)
return user, isBasic
}
}
Does it introduce new dependencies?
Yes, one additional direct dependency will be needed - github.com/quasoft/websspi (shameless plug, I am the author of this module).
Does SSPI require any complex setup in the AD environment?
No, the only configuration that is strictly required is to create a suitable Service Principal Name for the domain account that will be running the gitea.exe
process.
That is usually achieved by running the following command with a priviledged user:
setspn -A HTTP/host.domain.local domain\user
There are some gotchas the user might crash into while setting it up, which will be described in the Authentication
section of the documentation:
Gitea supports SPNEGO single sign-on authentication (the scheme defined by RFC4559) for the web part of the server via the Security Support Provider Interface (SSPI) built in Windows. SSPI works only in Windows environments - when both the server and the clients are running Windows.
Before activating SSPI single sign-on authentication (SSO) you have to prepare your environment:
- Create a separate user account in active directory, under which the
gitea.exe
process will be running (eg.user
under domaindomain.local
):- Create a service principal name for the host where
gitea.exe
is running with classHTTP
:- Start
Command Prompt
orPowerShell
as a priviledged domain user (eg. Domain Administrator)- Run the command below, replacing
host.domain.local
with the fully qualified domain name (FQDN) of the server where the web application will be running, anddomain\user
with the name of the account created in the previous step:setspn -A HTTP/host.domain.local domain\user
- Sign in (sign out if you were already signed in) with the user created
- Enable SSPI authentication by changing the
ENABLE_SSPI
value incustom/conf/app.ini
totrue
- Start the web server (
gitea.exe web
)- Sign in to a client computer in the same domain with any domain user
- If you are using Chrome, Edge or Internet Explorer, add the URL of the web app to the Local intranet sites (
Internet Options -> Security -> Local intranet -> Sites
)- Start Chrome, Edge or Internet Explorer and navigate to FQDN URL of gitea (eg.
http://host.domain.local:3000
)- Click the
Sign In
button on the dashboard and you should be automatically logged in with the same user that is currently logged on to the computer- If it does not work, make sure that:
- You are not running the web browser on the same server where gitea is running. You should be running the web browser on a domain joined computer (client) that is different from the server
- There is only one
HTTP/...
SPN for the host- The SPN contains only the hostname, without the port
- You have added the URL of the web app to the
Local intranet zone
- The clocks of the server and client should not differ with more than 5 minutes (depends on group policy)
Integrated Windows Authentication
should be enabled in Internet Explorer (underAdvanced settings
)