mirror of
https://github.com/zitadel/zitadel.git
synced 2025-06-08 11:28:34 +00:00
fix: bearer token encryption (#1524)
* fix: bearer token encryption * remove some todos
This commit is contained in:
parent
18aec74222
commit
27fcf4739d
@ -174,7 +174,7 @@ func startAPI(ctx context.Context, conf *Config, authZRepo *authz_repo.EsReposit
|
|||||||
apis.RegisterServer(ctx, auth.CreateServer(command, query, authRepo))
|
apis.RegisterServer(ctx, auth.CreateServer(command, query, authRepo))
|
||||||
}
|
}
|
||||||
if *oidcEnabled {
|
if *oidcEnabled {
|
||||||
op := oidc.NewProvider(ctx, conf.API.OIDC, command, query, authRepo, *localDevMode)
|
op := oidc.NewProvider(ctx, conf.API.OIDC, command, query, authRepo, conf.SystemDefaults.KeyConfig.EncryptionConfig, *localDevMode)
|
||||||
apis.RegisterHandler("/oauth/v2", op.HttpHandler())
|
apis.RegisterHandler("/oauth/v2", op.HttpHandler())
|
||||||
}
|
}
|
||||||
apis.Start(ctx)
|
apis.Start(ctx)
|
||||||
|
@ -8,7 +8,6 @@ export const cnslFormFieldAnimations: {
|
|||||||
} = {
|
} = {
|
||||||
/** Animation that transitions the form field's error and hint messages. */
|
/** Animation that transitions the form field's error and hint messages. */
|
||||||
transitionMessages: trigger('transitionMessages', [
|
transitionMessages: trigger('transitionMessages', [
|
||||||
// TODO(mmalerba): Use angular animations for label animation as well.
|
|
||||||
state('enter', style({ opacity: 1, transform: 'translateY(0%)' })),
|
state('enter', style({ opacity: 1, transform: 'translateY(0%)' })),
|
||||||
transition('void => enter', [
|
transition('void => enter', [
|
||||||
style({ opacity: 0, transform: 'translateY(-100%)' }),
|
style({ opacity: 0, transform: 'translateY(-100%)' }),
|
||||||
|
@ -63,8 +63,6 @@ export class CnslFormFieldComponent extends CnslFormFieldBase implements OnDestr
|
|||||||
@ContentChild(MatFormFieldControl) _controlNonStatic!: MatFormFieldControl<any>;
|
@ContentChild(MatFormFieldControl) _controlNonStatic!: MatFormFieldControl<any>;
|
||||||
@ContentChild(MatFormFieldControl, { static: true }) _controlStatic!: MatFormFieldControl<any>;
|
@ContentChild(MatFormFieldControl, { static: true }) _controlStatic!: MatFormFieldControl<any>;
|
||||||
get _control(): MatFormFieldControl<any> {
|
get _control(): MatFormFieldControl<any> {
|
||||||
// TODO(crisbeto): we need this workaround in order to support both Ivy and ViewEngine.
|
|
||||||
// We should clean this up once Ivy is the default renderer.
|
|
||||||
return this._explicitFormFieldControl || this._controlNonStatic || this._controlStatic;
|
return this._explicitFormFieldControl || this._controlNonStatic || this._controlStatic;
|
||||||
}
|
}
|
||||||
set _control(value: MatFormFieldControl<any>) {
|
set _control(value: MatFormFieldControl<any>) {
|
||||||
@ -139,7 +137,6 @@ export class CnslFormFieldComponent extends CnslFormFieldBase implements OnDestr
|
|||||||
if (this._control) {
|
if (this._control) {
|
||||||
const ids: string[] = [];
|
const ids: string[] = [];
|
||||||
|
|
||||||
// TODO(wagnermaciel): Remove the type check when we find the root cause of this bug.
|
|
||||||
if (this._control.userAriaDescribedBy &&
|
if (this._control.userAriaDescribedBy &&
|
||||||
typeof this._control.userAriaDescribedBy === 'string') {
|
typeof this._control.userAriaDescribedBy === 'string') {
|
||||||
ids.push(...this._control.userAriaDescribedBy.split(' '));
|
ids.push(...this._control.userAriaDescribedBy.split(' '));
|
||||||
|
@ -226,8 +226,6 @@ export class InputDirective extends _MatInputMixinBase implements MatFormFieldCo
|
|||||||
@Optional() @Self() @Inject(MAT_INPUT_VALUE_ACCESSOR) inputValueAccessor: any,
|
@Optional() @Self() @Inject(MAT_INPUT_VALUE_ACCESSOR) inputValueAccessor: any,
|
||||||
private _autofillMonitor: AutofillMonitor,
|
private _autofillMonitor: AutofillMonitor,
|
||||||
ngZone: NgZone,
|
ngZone: NgZone,
|
||||||
// TODO: Remove this once the legacy appearance has been removed. We only need
|
|
||||||
// to inject the form-field for determining whether the placeholder has been promoted.
|
|
||||||
@Optional() @Inject(MAT_FORM_FIELD) private _formField?: MatFormField) {
|
@Optional() @Inject(MAT_FORM_FIELD) private _formField?: MatFormField) {
|
||||||
|
|
||||||
super(_defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl);
|
super(_defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl);
|
||||||
@ -320,7 +318,6 @@ export class InputDirective extends _MatInputMixinBase implements MatFormFieldCo
|
|||||||
// We have to use a `HostListener` here in order to support both Ivy and ViewEngine.
|
// We have to use a `HostListener` here in order to support both Ivy and ViewEngine.
|
||||||
// In Ivy the `host` bindings will be merged when this class is extended, whereas in
|
// In Ivy the `host` bindings will be merged when this class is extended, whereas in
|
||||||
// ViewEngine they're overwritten.
|
// ViewEngine they're overwritten.
|
||||||
// TODO(crisbeto): we move this back into `host` once Ivy is turned on by default.
|
|
||||||
/** Callback for the cases where the focused state of the input changes. */
|
/** Callback for the cases where the focused state of the input changes. */
|
||||||
// tslint:disable:no-host-decorator-in-concrete
|
// tslint:disable:no-host-decorator-in-concrete
|
||||||
@HostListener('focus', ['true'])
|
@HostListener('focus', ['true'])
|
||||||
@ -336,7 +333,6 @@ export class InputDirective extends _MatInputMixinBase implements MatFormFieldCo
|
|||||||
// We have to use a `HostListener` here in order to support both Ivy and ViewEngine.
|
// We have to use a `HostListener` here in order to support both Ivy and ViewEngine.
|
||||||
// In Ivy the `host` bindings will be merged when this class is extended, whereas in
|
// In Ivy the `host` bindings will be merged when this class is extended, whereas in
|
||||||
// ViewEngine they're overwritten.
|
// ViewEngine they're overwritten.
|
||||||
// TODO(crisbeto): we move this back into `host` once Ivy is turned on by default.
|
|
||||||
// tslint:disable-next-line:no-host-decorator-in-concrete
|
// tslint:disable-next-line:no-host-decorator-in-concrete
|
||||||
@HostListener('input')
|
@HostListener('input')
|
||||||
_onInput(): void {
|
_onInput(): void {
|
||||||
@ -353,8 +349,6 @@ export class InputDirective extends _MatInputMixinBase implements MatFormFieldCo
|
|||||||
private _dirtyCheckPlaceholder(): void {
|
private _dirtyCheckPlaceholder(): void {
|
||||||
// If we're hiding the native placeholder, it should also be cleared from the DOM, otherwise
|
// If we're hiding the native placeholder, it should also be cleared from the DOM, otherwise
|
||||||
// screen readers will read it out twice: once from the label and once from the attribute.
|
// screen readers will read it out twice: once from the label and once from the attribute.
|
||||||
// TODO: can be removed once we get rid of the `legacy` style for the form field, because it's
|
|
||||||
// the only one that supports promoting the placeholder to a label.
|
|
||||||
const placeholder = this._formField?._hideControlPlaceholder?.() ? null : this.placeholder;
|
const placeholder = this._formField?._hideControlPlaceholder?.() ? null : this.placeholder;
|
||||||
if (placeholder !== this._previousPlaceholder) {
|
if (placeholder !== this._previousPlaceholder) {
|
||||||
const element = this._elementRef.nativeElement;
|
const element = this._elementRef.nativeElement;
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/auth/repository"
|
"github.com/caos/zitadel/internal/auth/repository"
|
||||||
"github.com/caos/zitadel/internal/command"
|
"github.com/caos/zitadel/internal/command"
|
||||||
"github.com/caos/zitadel/internal/config/types"
|
"github.com/caos/zitadel/internal/config/types"
|
||||||
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
"github.com/caos/zitadel/internal/id"
|
"github.com/caos/zitadel/internal/id"
|
||||||
"github.com/caos/zitadel/internal/query"
|
"github.com/caos/zitadel/internal/query"
|
||||||
"github.com/caos/zitadel/internal/telemetry/metrics"
|
"github.com/caos/zitadel/internal/telemetry/metrics"
|
||||||
@ -57,9 +58,16 @@ type OPStorage struct {
|
|||||||
signingKeyAlgorithm string
|
signingKeyAlgorithm string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProvider(ctx context.Context, config OPHandlerConfig, command *command.Commands, query *query.Queries, repo repository.Repository, localDevMode bool) op.OpenIDProvider {
|
func NewProvider(ctx context.Context, config OPHandlerConfig, command *command.Commands, query *query.Queries, repo repository.Repository, keyConfig *crypto.KeyConfig, localDevMode bool) op.OpenIDProvider {
|
||||||
cookieHandler, err := middleware.NewUserAgentHandler(config.UserAgentCookieConfig, id.SonyFlakeGenerator, localDevMode)
|
cookieHandler, err := middleware.NewUserAgentHandler(config.UserAgentCookieConfig, id.SonyFlakeGenerator, localDevMode)
|
||||||
logging.Log("OIDC-sd4fd").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Panic("cannot user agent handler")
|
logging.Log("OIDC-sd4fd").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Panic("cannot user agent handler")
|
||||||
|
tokenKey, err := crypto.LoadKey(keyConfig, keyConfig.EncryptionKeyID)
|
||||||
|
logging.Log("OIDC-ADvbv").OnError(err).Panic("cannot load OP crypto key")
|
||||||
|
cryptoKey := []byte(tokenKey)
|
||||||
|
if len(cryptoKey) != 32 {
|
||||||
|
logging.Log("OIDC-Dsfds").Panic("OP crypto key must be exactly 32 bytes")
|
||||||
|
}
|
||||||
|
copy(config.OPConfig.CryptoKey[:], cryptoKey)
|
||||||
config.OPConfig.CodeMethodS256 = true
|
config.OPConfig.CodeMethodS256 = true
|
||||||
metricTypes := []metrics.MetricType{metrics.MetricTypeRequestCount, metrics.MetricTypeStatusCode, metrics.MetricTypeTotalCount}
|
metricTypes := []metrics.MetricType{metrics.MetricTypeRequestCount, metrics.MetricTypeStatusCode, metrics.MetricTypeTotalCount}
|
||||||
provider, err := op.NewOpenIDProvider(
|
provider, err := op.NewOpenIDProvider(
|
||||||
|
@ -131,7 +131,8 @@ func (k *KeyRepository) refreshSigningKey(ctx context.Context, key *model.KeyVie
|
|||||||
}
|
}
|
||||||
signingKey, err := model.SigningKeyFromKeyView(key, k.KeyAlgorithm)
|
signingKey, err := model.SigningKeyFromKeyView(key, k.KeyAlgorithm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
logging.Log("EVENT-HJd92").WithError(err).Error("signing key cannot be decrypted -> immediate refresh")
|
||||||
|
return k.refreshSigningKey(ctx, nil, keyCh, algorithm)
|
||||||
}
|
}
|
||||||
k.currentKeyID = signingKey.ID
|
k.currentKeyID = signingKey.ID
|
||||||
k.currentKeyExpiration = key.Expiry
|
k.currentKeyExpiration = key.Expiry
|
||||||
|
@ -107,7 +107,8 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co
|
|||||||
IAMID: systemDefaults.IamID,
|
IAMID: systemDefaults.IamID,
|
||||||
},
|
},
|
||||||
eventstore.TokenRepo{
|
eventstore.TokenRepo{
|
||||||
View: view,
|
View: view,
|
||||||
|
Eventstore: es,
|
||||||
},
|
},
|
||||||
eventstore.KeyRepository{
|
eventstore.KeyRepository{
|
||||||
View: view,
|
View: view,
|
||||||
|
@ -26,7 +26,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type TokenVerifierRepo struct {
|
type TokenVerifierRepo struct {
|
||||||
TokenVerificationKey [32]byte
|
TokenVerificationKey crypto.EncryptionAlgorithm
|
||||||
IAMID string
|
IAMID string
|
||||||
Eventstore v1.Eventstore
|
Eventstore v1.Eventstore
|
||||||
View *view.View
|
View *view.View
|
||||||
@ -68,8 +68,7 @@ func (repo *TokenVerifierRepo) TokenByID(ctx context.Context, tokenID, userID st
|
|||||||
func (repo *TokenVerifierRepo) VerifyAccessToken(ctx context.Context, tokenString, clientID string) (userID string, agentID string, prefLang, resourceOwner string, err error) {
|
func (repo *TokenVerifierRepo) VerifyAccessToken(ctx context.Context, tokenString, clientID string) (userID string, agentID string, prefLang, resourceOwner string, err error) {
|
||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
//TODO: use real key
|
tokenIDSubject, err := repo.TokenVerificationKey.DecryptString([]byte(tokenString), repo.TokenVerificationKey.EncryptionKeyID())
|
||||||
tokenIDSubject, err := crypto.DecryptAESString(tokenString, string(repo.TokenVerificationKey[:32]))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", "", "", caos_errs.ThrowUnauthenticated(nil, "APP-8EF0zZ", "invalid token")
|
return "", "", "", "", caos_errs.ThrowUnauthenticated(nil, "APP-8EF0zZ", "invalid token")
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package eventsourcing
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
"github.com/caos/zitadel/internal/eventstore/v1"
|
"github.com/caos/zitadel/internal/eventstore/v1"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/query"
|
"github.com/caos/zitadel/internal/query"
|
||||||
@ -49,6 +50,11 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, qu
|
|||||||
|
|
||||||
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, systemDefaults)
|
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, systemDefaults)
|
||||||
|
|
||||||
|
keyAlgorithm, err := crypto.NewAESCrypto(systemDefaults.KeyConfig.EncryptionConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &EsRepository{
|
return &EsRepository{
|
||||||
spool,
|
spool,
|
||||||
eventstore.UserGrantRepo{
|
eventstore.UserGrantRepo{
|
||||||
@ -62,10 +68,10 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, qu
|
|||||||
IAMV2Query: queries,
|
IAMV2Query: queries,
|
||||||
},
|
},
|
||||||
eventstore.TokenVerifierRepo{
|
eventstore.TokenVerifierRepo{
|
||||||
//TODO: Add Token Verification Key
|
TokenVerificationKey: keyAlgorithm,
|
||||||
Eventstore: es,
|
Eventstore: es,
|
||||||
IAMID: systemDefaults.IamID,
|
IAMID: systemDefaults.IamID,
|
||||||
View: view,
|
View: view,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user