mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-13 11:34:26 +00:00
6b3f5b984c
* refactor: switch from opencensus to opentelemetry * tempo works as designed nooooot * fix: log traceids * with grafana agent * fix: http tracing * fix: cleanup files * chore: remove todo * fix: bad test * fix: ignore methods in grpc interceptors * fix: remove test log * clean up * typo * fix(config): configure tracing endpoint * fix(span): add error id to span * feat: metrics package * feat: metrics package * fix: counter * fix: metric * try metrics * fix: coutner metrics * fix: active sessin counter * fix: active sessin counter * fix: change current Sequence table * fix: change current Sequence table * fix: current sequences * fix: spooler div metrics * fix: console view * fix: merge master * fix: Last spool run on search result instead of eventtimestamp * fix: go mod * Update console/src/assets/i18n/de.json Co-authored-by: Livio Amstutz <livio.a@gmail.com> * fix: pr review * fix: map * update oidc pkg * fix: handlers * fix: value observer * fix: remove fmt * fix: handlers * fix: tests * fix: handler minimum cycle duration 1s * fix(spooler): handler channel buffer * fix interceptors Co-authored-by: adlerhurst <silvan.reusser@gmail.com> Co-authored-by: Livio Amstutz <livio.a@gmail.com>
124 lines
3.7 KiB
Go
124 lines
3.7 KiB
Go
package authz
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"sync"
|
|
|
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
|
)
|
|
|
|
const (
|
|
BearerPrefix = "Bearer "
|
|
)
|
|
|
|
type TokenVerifier struct {
|
|
authZRepo authZRepo
|
|
clients sync.Map
|
|
authMethods MethodMapping
|
|
}
|
|
|
|
type authZRepo interface {
|
|
VerifyAccessToken(ctx context.Context, token, clientID string) (userID, agentID, prefLang string, err error)
|
|
VerifierClientID(ctx context.Context, name string) (clientID string, err error)
|
|
ResolveGrants(ctx context.Context) (grant *Grant, err error)
|
|
ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (projectID string, origins []string, err error)
|
|
ExistsOrg(ctx context.Context, orgID string) error
|
|
}
|
|
|
|
func Start(authZRepo authZRepo) (v *TokenVerifier) {
|
|
return &TokenVerifier{authZRepo: authZRepo}
|
|
}
|
|
|
|
func (v *TokenVerifier) VerifyAccessToken(ctx context.Context, token string, method string) (userID, clientID, agentID, prefLang string, err error) {
|
|
clientID, err = v.clientIDFromMethod(ctx, method)
|
|
if err != nil {
|
|
return "", "", "", "", err
|
|
}
|
|
userID, agentID, prefLang, err = v.authZRepo.VerifyAccessToken(ctx, token, clientID)
|
|
return userID, clientID, agentID, prefLang, err
|
|
}
|
|
|
|
type client struct {
|
|
id string
|
|
name string
|
|
}
|
|
|
|
func (v *TokenVerifier) RegisterServer(appName, methodPrefix string, mappings MethodMapping) {
|
|
v.clients.Store(methodPrefix, &client{name: appName})
|
|
if v.authMethods == nil {
|
|
v.authMethods = make(map[string]Option)
|
|
}
|
|
for method, option := range mappings {
|
|
v.authMethods[method] = option
|
|
}
|
|
}
|
|
|
|
func prefixFromMethod(method string) (string, bool) {
|
|
parts := strings.Split(method, "/")
|
|
if len(parts) < 2 {
|
|
return "", false
|
|
}
|
|
return parts[1], true
|
|
}
|
|
|
|
func (v *TokenVerifier) clientIDFromMethod(ctx context.Context, method string) (_ string, err error) {
|
|
ctx, span := tracing.NewSpan(ctx)
|
|
defer func() { span.EndWithError(err) }()
|
|
|
|
prefix, ok := prefixFromMethod(method)
|
|
if !ok {
|
|
return "", caos_errs.ThrowPermissionDenied(nil, "AUTHZ-GRD2Q", "Errors.Internal")
|
|
}
|
|
app, ok := v.clients.Load(prefix)
|
|
if !ok {
|
|
return "", caos_errs.ThrowPermissionDenied(nil, "AUTHZ-G2qrh", "Errors.Internal")
|
|
}
|
|
c := app.(*client)
|
|
if c.id != "" {
|
|
return c.id, nil
|
|
}
|
|
c.id, err = v.authZRepo.VerifierClientID(ctx, c.name)
|
|
if err != nil {
|
|
return "", caos_errs.ThrowPermissionDenied(err, "AUTHZ-ptTIF2", "Errors.Internal")
|
|
}
|
|
v.clients.Store(prefix, c)
|
|
return c.id, nil
|
|
}
|
|
|
|
func (v *TokenVerifier) ResolveGrant(ctx context.Context) (_ *Grant, err error) {
|
|
ctx, span := tracing.NewSpan(ctx)
|
|
defer func() { span.EndWithError(err) }()
|
|
return v.authZRepo.ResolveGrants(ctx)
|
|
}
|
|
|
|
func (v *TokenVerifier) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (_ string, _ []string, err error) {
|
|
ctx, span := tracing.NewSpan(ctx)
|
|
defer func() { span.EndWithError(err) }()
|
|
|
|
return v.authZRepo.ProjectIDAndOriginsByClientID(ctx, clientID)
|
|
}
|
|
|
|
func (v *TokenVerifier) ExistsOrg(ctx context.Context, orgID string) (err error) {
|
|
ctx, span := tracing.NewSpan(ctx)
|
|
defer func() { span.EndWithError(err) }()
|
|
return v.authZRepo.ExistsOrg(ctx, orgID)
|
|
}
|
|
|
|
func (v *TokenVerifier) CheckAuthMethod(method string) (Option, bool) {
|
|
authOpt, ok := v.authMethods[method]
|
|
return authOpt, ok
|
|
}
|
|
|
|
func verifyAccessToken(ctx context.Context, token string, t *TokenVerifier, method string) (userID, clientID, agentID, prefLang string, err error) {
|
|
ctx, span := tracing.NewSpan(ctx)
|
|
defer func() { span.EndWithError(err) }()
|
|
|
|
parts := strings.Split(token, BearerPrefix)
|
|
if len(parts) != 2 {
|
|
return "", "", "", "", caos_errs.ThrowUnauthenticated(nil, "AUTH-7fs1e", "invalid auth header")
|
|
}
|
|
return t.VerifyAccessToken(ctx, parts[1], method)
|
|
}
|