aboutsummaryrefslogtreecommitdiffstats
path: root/services/auth/source/saml/source.go
diff options
context:
space:
mode:
Diffstat (limited to 'services/auth/source/saml/source.go')
-rw-r--r--services/auth/source/saml/source.go202
1 files changed, 0 insertions, 202 deletions
diff --git a/services/auth/source/saml/source.go b/services/auth/source/saml/source.go
deleted file mode 100644
index 52388646b5..0000000000
--- a/services/auth/source/saml/source.go
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2023 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-package saml
-
-import (
- "context"
- "crypto/rand"
- "crypto/rsa"
- "crypto/tls"
- "crypto/x509"
- "encoding/base64"
- "encoding/pem"
- "encoding/xml"
- "errors"
- "fmt"
- "math/big"
- "net/url"
- "time"
-
- "code.gitea.io/gitea/models/auth"
- "code.gitea.io/gitea/modules/json"
- "code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/setting"
-
- saml2 "github.com/russellhaering/gosaml2"
- "github.com/russellhaering/gosaml2/types"
- dsig "github.com/russellhaering/goxmldsig"
-)
-
-// Source holds configuration for the SAML login source.
-type Source struct {
- // IdentityProviderMetadata description: The SAML Identity Provider metadata XML contents (for static configuration of the SAML Service Provider). The value of this field should be an XML document whose root element is `<EntityDescriptor>` or `<EntityDescriptors>`. To escape the value into a JSON string, you may want to use a tool like https://json-escape-text.now.sh.
- IdentityProviderMetadata string
- // IdentityProviderMetadataURL description: The SAML Identity Provider metadata URL (for dynamic configuration of the SAML Service Provider).
- IdentityProviderMetadataURL string
- // InsecureSkipAssertionSignatureValidation description: Whether the Service Provider should (insecurely) accept assertions from the Identity Provider without a valid signature.
- InsecureSkipAssertionSignatureValidation bool
- // NameIDFormat description: The SAML NameID format to use when performing user authentication.
- NameIDFormat NameIDFormat
- // ServiceProviderCertificate description: The SAML Service Provider certificate in X.509 encoding (begins with "-----BEGIN CERTIFICATE-----"). This certificate is used by the Identity Provider to validate the Service Provider's AuthnRequests and LogoutRequests. It corresponds to the Service Provider's private key (`serviceProviderPrivateKey`). To escape the value into a JSON string, you may want to use a tool like https://json-escape-text.now.sh.
- ServiceProviderCertificate string
- // ServiceProviderIssuer description: The SAML Service Provider name, used to identify this Service Provider. This is required if the "externalURL" field is not set (as the SAML metadata endpoint is computed as "<externalURL>.auth/saml/metadata"), or when using multiple SAML authentication providers.
- ServiceProviderIssuer string
- // ServiceProviderPrivateKey description: The SAML Service Provider private key in PKCS#8 encoding (begins with "-----BEGIN PRIVATE KEY-----"). This private key is used to sign AuthnRequests and LogoutRequests. It corresponds to the Service Provider's certificate (`serviceProviderCertificate`). To escape the value into a JSON string, you may want to use a tool like https://json-escape-text.now.sh.
- ServiceProviderPrivateKey string
-
- CallbackURL string
- IconURL string
-
- // EmailAssertionKey description: Assertion key for user.Email
- EmailAssertionKey string
- // NameAssertionKey description: Assertion key for user.NickName
- NameAssertionKey string
- // UsernameAssertionKey description: Assertion key for user.Name
- UsernameAssertionKey string
-
- // reference to the authSource
- authSource *auth.Source
-
- samlSP *saml2.SAMLServiceProvider
-}
-
-func GenerateSAMLSPKeypair() (string, string, error) {
- key, err := rsa.GenerateKey(rand.Reader, 4096)
- if err != nil {
- return "", "", err
- }
-
- keyBytes := x509.MarshalPKCS1PrivateKey(key)
- keyPem := pem.EncodeToMemory(
- &pem.Block{
- Type: "RSA PRIVATE KEY",
- Bytes: keyBytes,
- },
- )
-
- now := time.Now()
-
- template := &x509.Certificate{
- SerialNumber: big.NewInt(0),
- NotBefore: now.Add(-5 * time.Minute),
- NotAfter: now.Add(365 * 24 * time.Hour),
-
- KeyUsage: x509.KeyUsageDigitalSignature,
- ExtKeyUsage: []x509.ExtKeyUsage{},
- BasicConstraintsValid: true,
- }
-
- certificate, err := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key)
- if err != nil {
- return "", "", err
- }
-
- certPem := pem.EncodeToMemory(
- &pem.Block{
- Type: "CERTIFICATE",
- Bytes: certificate,
- },
- )
-
- return string(keyPem), string(certPem), nil
-}
-
-func (source *Source) initSAMLSp() error {
- source.CallbackURL = setting.AppURL + "user/saml/" + url.PathEscape(source.authSource.Name) + "/acs"
-
- idpMetadata, err := readIdentityProviderMetadata(context.Background(), source)
- if err != nil {
- return err
- }
- {
- if source.IdentityProviderMetadataURL != "" {
- log.Trace(fmt.Sprintf("Identity Provider metadata: %s", source.IdentityProviderMetadataURL), string(idpMetadata))
- }
- }
-
- metadata := &types.EntityDescriptor{}
- err = xml.Unmarshal(idpMetadata, metadata)
- if err != nil {
- return err
- }
-
- certStore := dsig.MemoryX509CertificateStore{
- Roots: []*x509.Certificate{},
- }
-
- if metadata.IDPSSODescriptor == nil {
- return errors.New("saml idp metadata missing IDPSSODescriptor")
- }
-
- for _, kd := range metadata.IDPSSODescriptor.KeyDescriptors {
- for idx, xcert := range kd.KeyInfo.X509Data.X509Certificates {
- if xcert.Data == "" {
- return fmt.Errorf("metadata certificate(%d) must not be empty", idx)
- }
- certData, err := base64.StdEncoding.DecodeString(xcert.Data)
- if err != nil {
- return err
- }
-
- idpCert, err := x509.ParseCertificate(certData)
- if err != nil {
- return err
- }
-
- certStore.Roots = append(certStore.Roots, idpCert)
- }
- }
-
- var keyStore dsig.X509KeyStore
-
- if source.ServiceProviderCertificate != "" && source.ServiceProviderPrivateKey != "" {
- keyPair, err := tls.X509KeyPair([]byte(source.ServiceProviderCertificate), []byte(source.ServiceProviderPrivateKey))
- if err != nil {
- return err
- }
- keyPair.Leaf, err = x509.ParseCertificate(keyPair.Certificate[0])
- if err != nil {
- return err
- }
- keyStore = dsig.TLSCertKeyStore(keyPair)
- }
-
- source.samlSP = &saml2.SAMLServiceProvider{
- IdentityProviderSSOURL: metadata.IDPSSODescriptor.SingleSignOnServices[0].Location,
- IdentityProviderIssuer: metadata.EntityID,
- AudienceURI: setting.AppURL + "user/saml/" + url.PathEscape(source.authSource.Name) + "/metadata",
- AssertionConsumerServiceURL: source.CallbackURL,
- SkipSignatureValidation: source.InsecureSkipAssertionSignatureValidation,
- NameIdFormat: source.NameIDFormat.String(),
- IDPCertificateStore: &certStore,
- SignAuthnRequests: source.ServiceProviderCertificate != "" && source.ServiceProviderPrivateKey != "",
- SPKeyStore: keyStore,
- ServiceProviderIssuer: setting.AppURL + "user/saml/" + url.PathEscape(source.authSource.Name) + "/metadata",
- }
-
- return nil
-}
-
-// FromDB fills up a SAML from serialized format.
-func (source *Source) FromDB(bs []byte) error {
- if err := json.UnmarshalHandleDoubleEncode(bs, &source); err != nil {
- return err
- }
-
- return source.initSAMLSp()
-}
-
-// ToDB exports a SAML to a serialized format.
-func (source *Source) ToDB() ([]byte, error) {
- return json.Marshal(source)
-}
-
-// SetAuthSource sets the related AuthSource
-func (source *Source) SetAuthSource(authSource *auth.Source) {
- source.authSource = authSource
-}
-
-func init() {
- auth.RegisterTypeConfig(auth.SAML, &Source{})
-}