mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-13 19:44:21 +00:00
1aa8c49e41
# Which Problems Are Solved Zitadel never stored or returned the requested `response_mode` in oidc Auth Requests. This caused the oidc library to fallback to the default based on the response_type. # How the Problems Are Solved - Store the `response_mode` in the Auth request repo - Store the `response_mode` in the Auth request v2 events - Return the `resonse_mode` from the Auth Request v1 and v2 `ResponseMode()` methods. (Was hard-coded to an empty string) # Additional Changes - Populate the `response_modes_supported` to the oidc Discovery Configuration. When it was empty, the standard specifies the default of `query` and `fragment`. However, our oidc library also supports `form_post` and by this fix, zitadel now also supports this. # Additional Context - Closes #6586 - Reported https://discord.com/channels/927474939156643850/1151508313717084220 --------- Co-authored-by: Livio Spring <livio.a@gmail.com>
115 lines
3.6 KiB
Go
115 lines
3.6 KiB
Go
package command
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/zitadel/zitadel/internal/api/authz"
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
"github.com/zitadel/zitadel/internal/eventstore"
|
|
"github.com/zitadel/zitadel/internal/repository/authrequest"
|
|
"github.com/zitadel/zitadel/internal/zerrors"
|
|
)
|
|
|
|
type AuthRequestWriteModel struct {
|
|
eventstore.WriteModel
|
|
aggregate *eventstore.Aggregate
|
|
|
|
LoginClient string
|
|
ClientID string
|
|
RedirectURI string
|
|
State string
|
|
Nonce string
|
|
Scope []string
|
|
Audience []string
|
|
ResponseType domain.OIDCResponseType
|
|
ResponseMode domain.OIDCResponseMode
|
|
CodeChallenge *domain.OIDCCodeChallenge
|
|
Prompt []domain.Prompt
|
|
UILocales []string
|
|
MaxAge *time.Duration
|
|
LoginHint *string
|
|
HintUserID *string
|
|
SessionID string
|
|
UserID string
|
|
AuthTime time.Time
|
|
AuthMethods []domain.UserAuthMethodType
|
|
AuthRequestState domain.AuthRequestState
|
|
NeedRefreshToken bool
|
|
}
|
|
|
|
func NewAuthRequestWriteModel(ctx context.Context, id string) *AuthRequestWriteModel {
|
|
return &AuthRequestWriteModel{
|
|
WriteModel: eventstore.WriteModel{
|
|
AggregateID: id,
|
|
},
|
|
aggregate: &authrequest.NewAggregate(id, authz.GetInstance(ctx).InstanceID()).Aggregate,
|
|
}
|
|
}
|
|
|
|
func (m *AuthRequestWriteModel) Reduce() error {
|
|
for _, event := range m.Events {
|
|
switch e := event.(type) {
|
|
case *authrequest.AddedEvent:
|
|
m.LoginClient = e.LoginClient
|
|
m.ClientID = e.ClientID
|
|
m.RedirectURI = e.RedirectURI
|
|
m.State = e.State
|
|
m.Nonce = e.Nonce
|
|
m.Scope = e.Scope
|
|
m.Audience = e.Audience
|
|
m.ResponseType = e.ResponseType
|
|
m.ResponseMode = e.ResponseMode
|
|
m.CodeChallenge = e.CodeChallenge
|
|
m.Prompt = e.Prompt
|
|
m.UILocales = e.UILocales
|
|
m.MaxAge = e.MaxAge
|
|
m.LoginHint = e.LoginHint
|
|
m.HintUserID = e.HintUserID
|
|
m.AuthRequestState = domain.AuthRequestStateAdded
|
|
m.NeedRefreshToken = e.NeedRefreshToken
|
|
case *authrequest.SessionLinkedEvent:
|
|
m.SessionID = e.SessionID
|
|
m.UserID = e.UserID
|
|
m.AuthTime = e.AuthTime
|
|
m.AuthMethods = e.AuthMethods
|
|
case *authrequest.CodeAddedEvent:
|
|
m.AuthRequestState = domain.AuthRequestStateCodeAdded
|
|
case *authrequest.FailedEvent:
|
|
m.AuthRequestState = domain.AuthRequestStateFailed
|
|
case *authrequest.CodeExchangedEvent:
|
|
m.AuthRequestState = domain.AuthRequestStateCodeExchanged
|
|
case *authrequest.SucceededEvent:
|
|
m.AuthRequestState = domain.AuthRequestStateSucceeded
|
|
}
|
|
}
|
|
|
|
return m.WriteModel.Reduce()
|
|
}
|
|
|
|
func (m *AuthRequestWriteModel) Query() *eventstore.SearchQueryBuilder {
|
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
|
AddQuery().
|
|
AggregateTypes(authrequest.AggregateType).
|
|
AggregateIDs(m.AggregateID).
|
|
Builder()
|
|
}
|
|
|
|
// CheckAuthenticated checks that the auth request exists, a session must have been linked
|
|
// and in case of a Code Flow the code must have been exchanged
|
|
func (m *AuthRequestWriteModel) CheckAuthenticated() error {
|
|
if m.SessionID == "" {
|
|
return zerrors.ThrowPreconditionFailed(nil, "AUTHR-SF2r2", "Errors.AuthRequest.NotAuthenticated")
|
|
}
|
|
// in case of OIDC Code Flow, the code must have been exchanged
|
|
if m.ResponseType == domain.OIDCResponseTypeCode && m.AuthRequestState == domain.AuthRequestStateCodeExchanged {
|
|
return nil
|
|
}
|
|
// in case of OIDC Implicit Flow, check that the requests exists, but has not succeeded yet
|
|
if (m.ResponseType == domain.OIDCResponseTypeIDToken || m.ResponseType == domain.OIDCResponseTypeIDTokenToken) &&
|
|
m.AuthRequestState == domain.AuthRequestStateAdded {
|
|
return nil
|
|
}
|
|
return zerrors.ThrowPreconditionFailed(nil, "AUTHR-sajk3", "Errors.AuthRequest.NotAuthenticated")
|
|
}
|