Files
Lennart Fleischmann 062aee4d45 fix: SAML issues (#2041)
Rename identities table columns for more clarity. Rename parameters,
arguments etc. to accommodate these changes.
    
Change that the SAML provider domain is persisted in the identities
table as the provider ID. Use the SAML Entity ID/Issuer ID of the
IdP instead.
    
Introduce saml identity entity (including migrations and a persister)
as a specialization of an identity to allow for determining the
correct provider name to return to the client/frontend and for assisting
in determining whether an identity is a SAML identity (i.e. SAML
identities should have a corresponding SAML Identity instance while
OAuth/OIDC entities do not).
2025-01-31 14:17:52 +01:00

70 lines
2.3 KiB
Go

package models
import (
"errors"
"github.com/gobuffalo/pop/v6"
"github.com/gobuffalo/pop/v6/slices"
"github.com/gobuffalo/validate/v3"
"github.com/gobuffalo/validate/v3/validators"
"github.com/gofrs/uuid"
"time"
)
// Identity is used by pop to map your identities database table to your go code.
type Identity struct {
ID uuid.UUID `json:"id" db:"id"`
ProviderUserID string `json:"provider_user_id" db:"provider_user_id"`
ProviderID string `json:"provider_id" db:"provider_id"`
Data slices.Map `json:"data" db:"data"`
EmailID uuid.UUID `json:"email_id" db:"email_id"`
Email *Email `json:"email,omitempty" belongs_to:"email"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
SamlIdentity *SamlIdentity `json:"saml_identity" has_one:"saml_identity"`
}
type Identities []Identity
func (identities Identities) GetIdentity(providerID string, providerUserID string) *Identity {
for _, identity := range identities {
if identity.ProviderID == providerID && identity.ProviderUserID == providerUserID {
return &identity
}
}
return nil
}
func NewIdentity(providerID string, identityData map[string]interface{}, emailID uuid.UUID) (*Identity, error) {
providerUserID, ok := identityData["sub"]
if !ok {
return nil, errors.New("missing provider user id")
}
now := time.Now().UTC()
id, _ := uuid.NewV4()
identity := &Identity{
ID: id,
Data: identityData,
ProviderUserID: providerUserID.(string),
ProviderID: providerID,
EmailID: emailID,
CreatedAt: now,
UpdatedAt: now,
}
return identity, nil
}
// Validate gets run every time you call a "pop.Validate*" (pop.ValidateAndSave, pop.ValidateAndCreate, pop.ValidateAndUpdate) method.
// This method is not required and may be deleted.
func (i *Identity) Validate(tx *pop.Connection) (*validate.Errors, error) {
return validate.Validate(
&validators.UUIDIsPresent{Name: "ID", Field: i.ID},
&validators.StringIsPresent{Name: "ProviderUserID", Field: i.ProviderUserID},
&validators.StringIsPresent{Name: "ProviderID", Field: i.ProviderID},
&validators.TimeIsPresent{Name: "CreatedAt", Field: i.CreatedAt},
&validators.TimeIsPresent{Name: "UpdatedAt", Field: i.UpdatedAt},
), nil
}