mirror of
https://github.com/zitadel/zitadel.git
synced 2025-07-13 12:38:31 +00:00

# Which Problems Are Solved Remove the feature flag that allowed triggers in introspection. This option was a fallback in case introspection would not function properly without triggers. The API documentation asked for anyone using this flag to raise an issue. No such issue was received, hence we concluded it is safe to remove it. # How the Problems Are Solved - Remove flags from the system and instance level feature APIs. - Remove trigger functions that are no longer used - Adjust tests that used the flag. # Additional Changes - none # Additional Context - Closes #10026 - Flag was introduced in #7356 --------- Co-authored-by: Silvan <27845747+adlerhurst@users.noreply.github.com>
133 lines
4.3 KiB
Go
133 lines
4.3 KiB
Go
package oidc
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/muhlemmer/gu"
|
|
"github.com/zitadel/oidc/v3/pkg/oidc"
|
|
"github.com/zitadel/oidc/v3/pkg/op"
|
|
"golang.org/x/text/language"
|
|
|
|
"github.com/zitadel/zitadel/internal/command"
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
"github.com/zitadel/zitadel/internal/query"
|
|
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
|
"github.com/zitadel/zitadel/internal/user/model"
|
|
"github.com/zitadel/zitadel/internal/zerrors"
|
|
)
|
|
|
|
type accessToken struct {
|
|
tokenID string
|
|
userID string
|
|
resourceOwner string
|
|
subject string
|
|
preferredLanguage *language.Tag
|
|
clientID string
|
|
audience []string
|
|
scope []string
|
|
authMethods []domain.UserAuthMethodType
|
|
authTime time.Time
|
|
tokenCreation time.Time
|
|
tokenExpiration time.Time
|
|
isPAT bool
|
|
actor *domain.TokenActor
|
|
}
|
|
|
|
var ErrInvalidTokenFormat = errors.New("invalid token format")
|
|
|
|
func (s *Server) verifyAccessToken(ctx context.Context, tkn string) (_ *accessToken, err error) {
|
|
ctx, span := tracing.NewSpan(ctx)
|
|
defer func() { span.EndWithError(err) }()
|
|
|
|
var tokenID, subject string
|
|
|
|
if tokenIDSubject, err := s.Provider().Crypto().Decrypt(tkn); err == nil {
|
|
split := strings.Split(tokenIDSubject, ":")
|
|
if len(split) != 2 {
|
|
return nil, zerrors.ThrowPermissionDenied(ErrInvalidTokenFormat, "OIDC-rei1O", "token is not valid or has expired")
|
|
}
|
|
tokenID, subject = split[0], split[1]
|
|
} else {
|
|
verifier := op.NewAccessTokenVerifier(op.IssuerFromContext(ctx), s.accessTokenKeySet,
|
|
op.WithSupportedAccessTokenSigningAlgorithms(supportedSigningAlgs()...),
|
|
)
|
|
claims, err := op.VerifyAccessToken[*oidc.AccessTokenClaims](ctx, tkn, verifier)
|
|
if err != nil {
|
|
return nil, zerrors.ThrowPermissionDenied(err, "OIDC-Eib8e", "token is not valid or has expired")
|
|
}
|
|
tokenID, subject = claims.JWTID, claims.Subject
|
|
}
|
|
|
|
if strings.HasPrefix(tokenID, command.IDPrefixV2) {
|
|
token, err := s.query.ActiveAccessTokenByToken(ctx, tokenID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return accessTokenV2(tokenID, subject, token), nil
|
|
}
|
|
|
|
token, err := s.repo.TokenByIDs(ctx, subject, tokenID)
|
|
if err != nil {
|
|
return nil, zerrors.ThrowPermissionDenied(err, "OIDC-Dsfb2", "token is not valid or has expired")
|
|
}
|
|
return accessTokenV1(tokenID, subject, token), nil
|
|
}
|
|
|
|
func accessTokenV1(tokenID, subject string, token *model.TokenView) *accessToken {
|
|
var preferredLanguage *language.Tag
|
|
if token.PreferredLanguage != "" {
|
|
preferredLanguage = gu.Ptr(language.Make(token.PreferredLanguage))
|
|
}
|
|
return &accessToken{
|
|
tokenID: tokenID,
|
|
userID: token.UserID,
|
|
resourceOwner: token.ResourceOwner,
|
|
subject: subject,
|
|
preferredLanguage: preferredLanguage,
|
|
clientID: token.ApplicationID,
|
|
audience: token.Audience,
|
|
scope: token.Scopes,
|
|
tokenCreation: token.CreationDate,
|
|
tokenExpiration: token.Expiration,
|
|
isPAT: token.IsPAT,
|
|
actor: token.Actor,
|
|
}
|
|
}
|
|
|
|
func accessTokenV2(tokenID, subject string, token *query.OIDCSessionAccessTokenReadModel) *accessToken {
|
|
return &accessToken{
|
|
tokenID: tokenID,
|
|
userID: token.UserID,
|
|
resourceOwner: token.ResourceOwner,
|
|
subject: subject,
|
|
preferredLanguage: token.PreferredLanguage,
|
|
clientID: token.ClientID,
|
|
audience: token.Audience,
|
|
scope: token.Scope,
|
|
authMethods: token.AuthMethods,
|
|
authTime: token.AuthTime,
|
|
tokenCreation: token.AccessTokenCreation,
|
|
tokenExpiration: token.AccessTokenExpiration,
|
|
actor: token.Actor,
|
|
}
|
|
}
|
|
|
|
func (s *Server) assertClientScopesForPAT(ctx context.Context, token *accessToken, clientID, projectID string) error {
|
|
token.audience = append(token.audience, clientID, projectID)
|
|
projectIDQuery, err := query.NewProjectRoleProjectIDSearchQuery(projectID)
|
|
if err != nil {
|
|
return zerrors.ThrowInternal(err, "OIDC-Cyc78", "Errors.Internal")
|
|
}
|
|
roles, err := s.query.SearchProjectRoles(ctx, false, &query.ProjectRoleSearchQueries{Queries: []query.SearchQuery{projectIDQuery}}, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, role := range roles.ProjectRoles {
|
|
token.scope = append(token.scope, ScopeProjectRolePrefix+role.Key)
|
|
}
|
|
return nil
|
|
}
|