zitadel/internal/command/saml_request.go

162 lines
5.4 KiB
Go
Raw Normal View History

package command
import (
"context"
"time"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/repository/samlrequest"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
"github.com/zitadel/zitadel/internal/zerrors"
)
type SAMLRequest struct {
ID string
LoginClient string
ApplicationID string
ACSURL string
RelayState string
RequestID string
Binding string
Issuer string
Destination string
}
type CurrentSAMLRequest struct {
*SAMLRequest
SessionID string
UserID string
AuthMethods []domain.UserAuthMethodType
AuthTime time.Time
}
func (c *Commands) AddSAMLRequest(ctx context.Context, samlRequest *SAMLRequest) (_ *CurrentSAMLRequest, err error) {
id, err := c.idGenerator.Next()
if err != nil {
return nil, err
}
samlRequest.ID = IDPrefixV2 + id
writeModel, err := c.getSAMLRequestWriteModel(ctx, samlRequest.ID)
if err != nil {
return nil, err
}
if writeModel.SAMLRequestState != domain.SAMLRequestStateUnspecified {
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-MO3vmsMLUt", "Errors.SAMLRequest.AlreadyExisting")
}
err = c.pushAppendAndReduce(ctx, writeModel, samlrequest.NewAddedEvent(
ctx,
&samlrequest.NewAggregate(samlRequest.ID, authz.GetInstance(ctx).InstanceID()).Aggregate,
samlRequest.LoginClient,
samlRequest.ApplicationID,
samlRequest.ACSURL,
samlRequest.RelayState,
samlRequest.RequestID,
samlRequest.Binding,
samlRequest.Issuer,
samlRequest.Destination,
))
if err != nil {
return nil, err
}
return samlRequestWriteModelToCurrentSAMLRequest(writeModel), nil
}
func (c *Commands) LinkSessionToSAMLRequest(ctx context.Context, id, sessionID, sessionToken string, checkLoginClient bool) (*domain.ObjectDetails, *CurrentSAMLRequest, error) {
writeModel, err := c.getSAMLRequestWriteModel(ctx, id)
if err != nil {
return nil, nil, err
}
if writeModel.SAMLRequestState == domain.SAMLRequestStateUnspecified {
return nil, nil, zerrors.ThrowNotFound(nil, "COMMAND-GH3PVLSfXC", "Errors.SAMLRequest.NotExisting")
}
if writeModel.SAMLRequestState != domain.SAMLRequestStateAdded {
return nil, nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-ttPKNdAIFT", "Errors.SAMLRequest.AlreadyHandled")
}
if checkLoginClient && authz.GetCtxData(ctx).UserID != writeModel.LoginClient {
return nil, nil, zerrors.ThrowPermissionDenied(nil, "COMMAND-KCd48Rxt7x", "Errors.SAMLRequest.WrongLoginClient")
}
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetInstance(ctx).InstanceID())
err = c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel)
if err != nil {
return nil, nil, err
}
if err = sessionWriteModel.CheckIsActive(); err != nil {
return nil, nil, err
}
if err := c.sessionTokenVerifier(ctx, sessionToken, sessionWriteModel.AggregateID, sessionWriteModel.TokenID); err != nil {
return nil, nil, err
}
if err := c.pushAppendAndReduce(ctx, writeModel, samlrequest.NewSessionLinkedEvent(
ctx, &samlrequest.NewAggregate(id, authz.GetInstance(ctx).InstanceID()).Aggregate,
sessionID,
sessionWriteModel.UserID,
sessionWriteModel.AuthenticationTime(),
sessionWriteModel.AuthMethodTypes(),
)); err != nil {
return nil, nil, err
}
return writeModelToObjectDetails(&writeModel.WriteModel), samlRequestWriteModelToCurrentSAMLRequest(writeModel), nil
}
func (c *Commands) FailSAMLRequest(ctx context.Context, id string, reason domain.SAMLErrorReason) (*domain.ObjectDetails, *CurrentSAMLRequest, error) {
writeModel, err := c.getSAMLRequestWriteModel(ctx, id)
if err != nil {
return nil, nil, err
}
if writeModel.SAMLRequestState != domain.SAMLRequestStateAdded {
return nil, nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-32lGj1Fhjt", "Errors.SAMLRequest.AlreadyHandled")
}
err = c.pushAppendAndReduce(ctx, writeModel, samlrequest.NewFailedEvent(
ctx,
&samlrequest.NewAggregate(id, authz.GetInstance(ctx).InstanceID()).Aggregate,
reason,
))
if err != nil {
return nil, nil, err
}
return writeModelToObjectDetails(&writeModel.WriteModel), samlRequestWriteModelToCurrentSAMLRequest(writeModel), nil
}
func samlRequestWriteModelToCurrentSAMLRequest(writeModel *SAMLRequestWriteModel) (_ *CurrentSAMLRequest) {
return &CurrentSAMLRequest{
SAMLRequest: &SAMLRequest{
ID: writeModel.AggregateID,
LoginClient: writeModel.LoginClient,
ApplicationID: writeModel.ApplicationID,
ACSURL: writeModel.ACSURL,
RelayState: writeModel.RelayState,
RequestID: writeModel.RequestID,
Binding: writeModel.Binding,
Issuer: writeModel.Issuer,
Destination: writeModel.Destination,
},
SessionID: writeModel.SessionID,
UserID: writeModel.UserID,
AuthMethods: writeModel.AuthMethods,
AuthTime: writeModel.AuthTime,
}
}
func (c *Commands) GetCurrentSAMLRequest(ctx context.Context, id string) (_ *CurrentSAMLRequest, err error) {
wm, err := c.getSAMLRequestWriteModel(ctx, id)
if err != nil {
return nil, err
}
return samlRequestWriteModelToCurrentSAMLRequest(wm), nil
}
func (c *Commands) getSAMLRequestWriteModel(ctx context.Context, id string) (writeModel *SAMLRequestWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel = NewSAMLRequestWriteModel(ctx, id)
err = c.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}