Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support SAML authentication #29403

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/pull-db-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ jobs:
MINIO_ROOT_PASSWORD: 12345678
ports:
- "9000:9000"
simplesaml:
image: allspice/simple-saml
ports:
- "8080:8080"
env:
SIMPLESAMLPHP_SP_ENTITY_ID: http://localhost:3002/user/saml/test-sp/metadata
SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE: http://localhost:3002/user/saml/test-sp/acs
SIMPLESAMLPHP_SP_SINGLE_LOGOUT_SERVICE: http://localhost:3002/user/saml/test-sp/acs
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
Expand Down
25 changes: 25 additions & 0 deletions assets/go-licenses.json

Large diffs are not rendered by default.

69 changes: 69 additions & 0 deletions docs/content/usage/authentication.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,3 +349,72 @@ If set `ENABLE_REVERSE_PROXY_FULL_NAME=true`, a user full name expected in `X-WE
You can also limit the reverse proxy's IP address range with `REVERSE_PROXY_TRUSTED_PROXIES` which default value is `127.0.0.0/8,::1/128`. By `REVERSE_PROXY_LIMIT`, you can limit trusted proxies level.

Notice: Reverse Proxy Auth doesn't support the API. You still need an access token or basic auth to make API requests.

## SAML

### Configuring Gitea as a SAML 2.0 Service Provider

- Navigate to `Site Administration > Identity & Access > Authentication Sources`.
- Click the `Add Authentication Source` button.
- Select `SAML` as the authentication type.

#### Features Not Yet Supported

Currently, auto-registration is not supported for SAML. During the external account linking process the user will be prompted to set a username and email address or link to an existing account.

SAML group mapping is not supported.

#### Settings

- `Authentication Name` **(required)**

- The name of this authentication source (appears in the Gitea ACS and metadata URLs)

- `SAML NameID Format` **(required)**

- This specifies how Identity Provider (IdP) users are mapped to Gitea users. This option will be provider specific.

- `Icon URL` (optional)

- URL of an icon to display on the Sign-In page for this authentication source.

- `[Insecure] Skip Assertion Signature Validation` (optional)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would this be even a thing? It's like adding an option to not check the user's password in the login form...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@techknowlogick Can we remove this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's correct that it's incredibly insecure, as it bypasses any validation checks for the data that is sent to it, which is via HTTP post so it is accessible to the user, so the user can modify it in transit if validation checks are not added. It definitely shouldn't be enabled on production systems (after any setup has been done), or even if it does get enabled it should be disabled soon after (even if a system is in testing mode), and disabling access to the application expect to specific machines (likely done via reverse proxy IP allow list) during the time it is enabled.

This was added intentionally, though, for the reason that for debugging purposes in many other systems that support saml provide this as an option. It is to see if the saml is sending the required assertions and the application is parsing it into the correct user fields, and being able to debug that portion prior to seeing if it is a cert error.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I see this feature as useful for development it still should not be an option for the end-user

Copy link
Member

@delvh delvh Mar 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about marking it in the documentation as

⚠️ ⚠️ ⚠️ (experimental) only for debugging purposes and horribly insecure. Might be removed at any time.

?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that would probably be ok in combination with warnings and confirm dialog that states risks when saving auth source

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this shouldn't be in the source code at all. If it stays, why not also have an option saying "Bypass password verification for all local users"?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was added intentionally, though, for the reason that for debugging purposes in many other systems that support saml provide this as an option. It is to see if the saml is sending the required assertions and the application is parsing it into the correct user fields, and being able to debug that portion prior to seeing if it is a cert error.

It won't help them if the error is so generic that they cannot tell if it's a missing assertion or invalid signature. This should be fixed with proper error handling that says "Assertion rejected, invalid signature" or "Assertion rejected, unable to determine username", not a "allow anyone access to any account on this Gitea instance by checking this one box"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't speak for all use-cases, but I have found this option (in other systems) to be incredibly helpful in the past. As not having control over both sides of the auth portion, being able to disable the signing portion, had allowed me to let the IAM team know to please check the certs, and it was a quick solve (this sadly happened to me more than once). 99% of the time issues I've run into have been cert related.
I'd disagree that adding a "bypass password check for all users" would be equal, as in that case you would already know if the database had failed, and for ldap the errors would be more specific to what type of tls error is happening.

That being said, I think I'm the only one advocating for the inclusion of this though, and so I'll suggest a poll that'll happen out over the next week (ending the morning of Mar25) to get a gauge from everyone:
😄 include the debug option, but make sure to have the strict language above regarding the warning, including a red banner for admins on each page, and possibly a cronjob to disable to setting after an hour.
🎉 remove the debug option fully

and whatever the results are, I'll follow them.

(if the poll can be updated to use different language, or some other adjustments, please respond below and I'll be happy to update).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess with the results tied (if we add my vote in) then I will go ahead with the removal.


- This option is not recommended and disables integrity verification of IdP SAML assertions.

- `Identity Provider Metadata URL` (optional if XML set)

- The URL of the IdP metadata endpoint.
- This field must be set if `Identity Provider Metadata XML` is left blank.

- `Identity Provider Metadata XML` (optional if URL set)

- The XML returned by the IdP metadata endpoint.
- This field must be set if `Identity Provider Metadata URL` is left blank.

- `Service Provider Certificate` (optional)

- X.509-formatted certificate (with `Service Provider Private Key`) used for signing SAML requests.
- A certificate will be generated if this field is left blank.

- `Service Provider Private Key` (optional)

- DSA/RSA private key (with `Service Provider Certificate`) used for signing SAML requests.
- A private key will be generated if this field is left blank.

- `Email Assertion Key` (optional)

- The SAML assertion key used for the IdP user's email (depends on provider configuration).

- `Name Assertion Key` (optional)

- The SAML assertion key used for the IdP user's nickname (depends on provider configuration).

- `Username Assertion Key` (optional)

- The SAML assertion key used for the IdP user's username (depends on provider configuration).

### Configuring a SAML 2.0 Identity Provider to use Gitea

- The service provider assertion consumer service url will look like: `http(s)://[mydomain]/user/saml/[Authentication Name]/acs`.
- The service provider metadata url will look like: `http(s)://[mydomain]/user/saml/[Authentication Name]/metadata`.
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ require (
github.com/quasoft/websspi v1.1.2
github.com/redis/go-redis/v9 v9.5.1
github.com/robfig/cron/v3 v3.0.1
github.com/russellhaering/gosaml2 v0.9.1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found a more popular package(crewjam/saml) that we can use. It looks like russellhaering/gosaml2 only supports HTTP POST binding, but crewjam/saml supports both HTTP Redirect binding and HTTP POST binding.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you make a pull against my feature branch we can test that lib :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PS: it's no simple drop-in replacement :/

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Zettat123 the pull is not originally from me but was just resubmited for review.

so @techknowlogick or @jackHay22 might know more about why thy have choosen the lib?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Zettat123 I'll added it to the followups is that ok or should we wait for the others to respond?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion here; if the additional features are useful this would be a good time to make the switch.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Zettat123 It looks like gosaml2 supports HTTP redirect binding. Let me know if I'm missing something.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found an issue related to the Redirect binding. I haven't looked into this issue, but it looks like there is a workaround. But I think this issue not being solved for a long time means that the project is not very active.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't disagree but I think the crewjam/saml repo also has signs of inactivity.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think at some point a saml lib is just completed and only needs version bumps if it has dependencys?

so in this regards if there are no issues open anymore I'm fine with a inactive lib.

here both repos still have open issues :/

github.com/russellhaering/goxmldsig v1.3.0
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
github.com/sassoftware/go-rpmutils v0.3.0
github.com/sergi/go-diff v1.3.1
Expand Down Expand Up @@ -143,6 +145,7 @@ require (
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beevik/etree v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.13.0 // indirect
github.com/blevesearch/bleve_index_api v1.1.6 // indirect
Expand Down Expand Up @@ -216,6 +219,7 @@ require (
github.com/imdario/mergo v0.3.16 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jessevdk/go-flags v1.5.0 // indirect
github.com/jonboulle/clockwork v0.3.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
Expand All @@ -225,6 +229,7 @@ require (
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/markbates/going v1.0.3 // indirect
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mholt/acmez v1.2.0 // indirect
Expand Down
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bits-and-blooms/bitset v1.1.10/go.mod h1:w0XsmFg8qg6cmpTtJ0z3pKgjTDBMMnI/+I2syrE6XBE=
Expand Down Expand Up @@ -473,6 +475,9 @@ github.com/jhillyerd/enmime v1.2.0 h1:dIu1IPEymQgoT2dzuB//ttA/xcV40NMPpQtmd4wslH
github.com/jhillyerd/enmime v1.2.0/go.mod h1:FRFuUPCLh8PByQv+8xRcLO9QHqaqTqreYhopv5eyk4I=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg=
github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
Expand Down Expand Up @@ -532,6 +537,8 @@ github.com/markbates/going v1.0.3 h1:mY45T5TvW+Xz5A6jY7lf4+NLg9D8+iuStIHyR7M8qsE
github.com/markbates/going v1.0.3/go.mod h1:fQiT6v6yQar9UD6bd/D4Z5Afbk9J6BBVBtLiyY4gp2o=
github.com/markbates/goth v1.79.0 h1:fUYi9R6VubVEK2bpmXvIUp7xRcxA68i8ovfUQx/i5Qc=
github.com/markbates/goth v1.79.0/go.mod h1:RBD+tcFnXul2NnYuODhnIweOcuVPkBohLfEvutPekcU=
github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU=
github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
Expand Down Expand Up @@ -660,12 +667,17 @@ github.com/robertkrimen/godocdown v0.0.0-20130622164427-0bfa04905481/go.mod h1:C
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/russellhaering/gosaml2 v0.9.1 h1:H/whrl8NuSoxyW46Ww5lKPskm+5K+qYLw9afqJ/Zef0=
github.com/russellhaering/gosaml2 v0.9.1/go.mod h1:ja+qgbayxm+0mxBRLMSUuX3COqy+sb0RRhIGun/W2kc=
github.com/russellhaering/goxmldsig v1.3.0 h1:DllIWUgMy0cRUMfGiASiYEa35nsieyD3cigIwLonTPM=
github.com/russellhaering/goxmldsig v1.3.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
Expand Down
20 changes: 5 additions & 15 deletions models/auth/oauth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"crypto/sha256"
"encoding/base32"
"encoding/base64"
"encoding/gob"
"fmt"
"net"
"net/url"
Expand Down Expand Up @@ -81,6 +82,10 @@ func Init(ctx context.Context) error {
builtinAllClientIDs = append(builtinAllClientIDs, clientID)
}

// This is needed in order to encode and store the struct in the goth/gothic session
// during the process of linking the external user.
gob.Register(LinkAccountUser{})

var registeredApps []*OAuth2Application
if err := db.GetEngine(ctx).In("client_id", builtinAllClientIDs).Find(&registeredApps); err != nil {
return err
Expand Down Expand Up @@ -605,21 +610,6 @@ func (err ErrOAuthApplicationNotFound) Unwrap() error {
return util.ErrNotExist
}

// GetActiveOAuth2SourceByName returns a OAuth2 AuthSource based on the given name
func GetActiveOAuth2SourceByName(ctx context.Context, name string) (*Source, error) {
authSource := new(Source)
has, err := db.GetEngine(ctx).Where("name = ? and type = ? and is_active = ?", name, OAuth2, true).Get(authSource)
if err != nil {
return nil, err
}

if !has {
return nil, fmt.Errorf("oauth2 source not found, name: %q", name)
}

return authSource, nil
}

func DeleteOAuth2RelictsByUserID(ctx context.Context, userID int64) error {
deleteCond := builder.Select("id").From("oauth2_grant").Where(builder.Eq{"oauth2_grant.user_id": userID})

Expand Down
38 changes: 38 additions & 0 deletions models/auth/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"

"github.com/markbates/goth"
"xorm.io/builder"
"xorm.io/xorm"
"xorm.io/xorm/convert"
Expand All @@ -33,6 +34,7 @@ const (
DLDAP // 5
OAuth2 // 6
SSPI // 7
SAML // 8
)

// String returns the string name of the LoginType
Expand All @@ -53,6 +55,7 @@ var Names = map[Type]string{
PAM: "PAM",
OAuth2: "OAuth2",
SSPI: "SPNEGO with SSPI",
SAML: "SAML",
}

// Config represents login config as far as the db is concerned
Expand Down Expand Up @@ -122,6 +125,12 @@ type Source struct {
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}

// LinkAccountUser is used to link an external user with a local user
type LinkAccountUser struct {
Type Type
GothUser goth.User
}

// TableName xorm will read the table name from this method
func (Source) TableName() string {
return "login_source"
Expand Down Expand Up @@ -181,6 +190,11 @@ func (source *Source) IsSSPI() bool {
return source.Type == SSPI
}

// IsSAML returns true of this source is of the SAML type.
func (source *Source) IsSAML() bool {
return source.Type == SAML
}

// HasTLS returns true of this source supports TLS.
func (source *Source) HasTLS() bool {
hasTLSer, ok := source.Cfg.(HasTLSer)
Expand Down Expand Up @@ -393,3 +407,27 @@ func IsErrSourceInUse(err error) bool {
func (err ErrSourceInUse) Error() string {
return fmt.Sprintf("login source is still used by some users [id: %d]", err.ID)
}

// GetActiveAuthProviderSources returns all activated sources
func GetActiveAuthProviderSources(ctx context.Context, authType Type) ([]*Source, error) {
sources := make([]*Source, 0, 1)
if err := db.GetEngine(ctx).Where("is_active = ? and type = ?", true, authType).Find(&sources); err != nil {
return nil, err
}
return sources, nil
}

// GetActiveAuthSourceByName returns an AuthSource based on the given name and type
func GetActiveAuthSourceByName(ctx context.Context, name string, authType Type) (*Source, error) {
authSource := new(Source)
has, err := db.GetEngine(ctx).Where("name = ? and type = ? and is_active = ?", name, authType, true).Get(authSource)
if err != nil {
return nil, err
}

if !has {
return nil, fmt.Errorf("auth source not found, name: %q", name)
}

return authSource, nil
}
14 changes: 14 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,9 @@ Content = Content
SSPISeparatorReplacement = Separator
SSPIDefaultLanguage = Default Language

SAMLMetadata = Either SAML Identity Provider metadata URL or XML
SAMLMetadataURL = SAML Identity Provider metadata URL is invalid

require_error = ` cannot be empty.`
alpha_dash_error = ` should contain only alphanumeric, dash ('-') and underscore ('_') characters.`
alpha_dash_dot_error = ` should contain only alphanumeric, dash ('-'), underscore ('_') and dot ('.') characters.`
Expand Down Expand Up @@ -3082,7 +3085,18 @@ auths.sspi_separator_replacement = Separator to use instead of \, / and @
auths.sspi_separator_replacement_helper = 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 "user@example.org").
auths.sspi_default_language = Default user language
auths.sspi_default_language_helper = Default language for users automatically created by SSPI auth method. Leave empty if you prefer language to be automatically detected.
auths.saml_nameidformat = SAML NameID Format
auths.saml_identity_provider_metadata_url = Identity Provider Metadata URL
auths.saml_identity_provider_metadata = Identity Provider Metadata XML
auths.saml_insecure_skip_assertion_signature_validation = [Insecure] Skip Assertion Signature Validation
auths.saml_service_provider_certificate = Service Provider Certificate
auths.saml_service_provider_private_key = Service Provider Private Key
auths.saml_identity_provider_email_assertion_key = Email Assertion Key
auths.saml_identity_provider_name_assertion_key = Name Assertion Key
auths.saml_identity_provider_username_assertion_key = Username Assertion Key
auths.saml_icon_url = Icon URL
auths.tips = Tips
auths.tips.saml = Documentation can be found at https://docs.gitea.com/usage/authentication#saml
auths.tips.oauth2.general = OAuth2 Authentication
auths.tips.oauth2.general.tip = When registering a new OAuth2 authentication, the callback/redirect URL should be:
auths.tip.oauth2_provider = OAuth2 Provider
Expand Down
2 changes: 2 additions & 0 deletions routers/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
asymkey_service "code.gitea.io/gitea/services/asymkey"
"code.gitea.io/gitea/services/auth"
"code.gitea.io/gitea/services/auth/source/oauth2"
"code.gitea.io/gitea/services/auth/source/saml"
"code.gitea.io/gitea/services/automerge"
"code.gitea.io/gitea/services/cron"
feed_service "code.gitea.io/gitea/services/feed"
Expand Down Expand Up @@ -138,6 +139,7 @@ func InitWebInstalled(ctx context.Context) {
log.Info("ORM engine initialization successful!")
mustInit(system.Init)
mustInitCtx(ctx, oauth2.Init)
mustInitCtx(ctx, saml.Init)

mustInit(release_service.Init)

Expand Down
Loading
Loading