diff --git a/go.mod b/go.mod index 36ae667139..6aca2ced0d 100644 --- a/go.mod +++ b/go.mod @@ -63,7 +63,7 @@ require ( github.com/onsi/ginkgo/v2 v2.23.1 github.com/onsi/gomega v1.36.2 github.com/open-policy-agent/opa v1.2.0 - github.com/opencloud-eu/reva/v2 v2.28.1-0.20250320105919-be91238e6b11 + github.com/opencloud-eu/reva/v2 v2.28.1-0.20250320135948-a946c0d6d289 github.com/orcaman/concurrent-map v1.0.0 github.com/owncloud/libre-graph-api-go v1.0.5-0.20240829135935-80dc00d6f5ea github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 60e8a67477..278bfb2255 100644 --- a/go.sum +++ b/go.sum @@ -861,8 +861,8 @@ github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= github.com/open-policy-agent/opa v1.2.0 h1:88NDVCM0of1eO6Z4AFeL3utTEtMuwloFmWWU7dRV1z0= github.com/open-policy-agent/opa v1.2.0/go.mod h1:30euUmOvuBoebRCcJ7DMF42bRBOPznvt0ACUMYDUGVY= -github.com/opencloud-eu/reva/v2 v2.28.1-0.20250320105919-be91238e6b11 h1:MjfgrhEs73BezOXQZUgEtNTZsmXDVixFpGzZljR5lrk= -github.com/opencloud-eu/reva/v2 v2.28.1-0.20250320105919-be91238e6b11/go.mod h1:iK0tNdLgqK0zBi0l7Q4uWSn9GPUbYtNxz3YAMfYvYNg= +github.com/opencloud-eu/reva/v2 v2.28.1-0.20250320135948-a946c0d6d289 h1:gg37XG4j3Y7yWLrD+B+2uNQ72g4YasdvpzOKJnuQH1Y= +github.com/opencloud-eu/reva/v2 v2.28.1-0.20250320135948-a946c0d6d289/go.mod h1:iK0tNdLgqK0zBi0l7Q4uWSn9GPUbYtNxz3YAMfYvYNg= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= diff --git a/opencloud/pkg/runtime/service/service.go b/opencloud/pkg/runtime/service/service.go index 780b57a5cf..0220154e4d 100644 --- a/opencloud/pkg/runtime/service/service.go +++ b/opencloud/pkg/runtime/service/service.go @@ -11,17 +11,9 @@ import ( "strings" "time" - authapp "github.com/opencloud-eu/opencloud/services/auth-app/pkg/command" - "github.com/cenkalti/backoff" "github.com/mohae/deepcopy" "github.com/olekukonko/tablewriter" - notifications "github.com/opencloud-eu/opencloud/services/notifications/pkg/command" - "github.com/opencloud-eu/reva/v2/pkg/events/stream" - "github.com/opencloud-eu/reva/v2/pkg/logger" - "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" - "github.com/thejerf/suture/v4" - occfg "github.com/opencloud-eu/opencloud/pkg/config" "github.com/opencloud-eu/opencloud/pkg/log" ogrpc "github.com/opencloud-eu/opencloud/pkg/service/grpc" @@ -31,6 +23,7 @@ import ( appProvider "github.com/opencloud-eu/opencloud/services/app-provider/pkg/command" appRegistry "github.com/opencloud-eu/opencloud/services/app-registry/pkg/command" audit "github.com/opencloud-eu/opencloud/services/audit/pkg/command" + authapp "github.com/opencloud-eu/opencloud/services/auth-app/pkg/command" authbasic "github.com/opencloud-eu/opencloud/services/auth-basic/pkg/command" authmachine "github.com/opencloud-eu/opencloud/services/auth-machine/pkg/command" authservice "github.com/opencloud-eu/opencloud/services/auth-service/pkg/command" @@ -44,6 +37,7 @@ import ( idp "github.com/opencloud-eu/opencloud/services/idp/pkg/command" invitations "github.com/opencloud-eu/opencloud/services/invitations/pkg/command" nats "github.com/opencloud-eu/opencloud/services/nats/pkg/command" + notifications "github.com/opencloud-eu/opencloud/services/notifications/pkg/command" ocdav "github.com/opencloud-eu/opencloud/services/ocdav/pkg/command" ocm "github.com/opencloud-eu/opencloud/services/ocm/pkg/command" ocs "github.com/opencloud-eu/opencloud/services/ocs/pkg/command" @@ -64,6 +58,10 @@ import ( web "github.com/opencloud-eu/opencloud/services/web/pkg/command" webdav "github.com/opencloud-eu/opencloud/services/webdav/pkg/command" webfinger "github.com/opencloud-eu/opencloud/services/webfinger/pkg/command" + "github.com/opencloud-eu/reva/v2/pkg/events/stream" + "github.com/opencloud-eu/reva/v2/pkg/logger" + "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" + "github.com/thejerf/suture/v4" ) var ( @@ -160,6 +158,11 @@ func NewService(ctx context.Context, options ...Option) (*Service, error) { cfg.AppRegistry.Commons = cfg.Commons return appRegistry.Execute(cfg.AppRegistry) }) + reg(3, opts.Config.AuthApp.Service.Name, func(ctx context.Context, cfg *occfg.Config) error { + cfg.AuthApp.Context = ctx + cfg.AuthApp.Commons = cfg.Commons + return authapp.Execute(cfg.AuthApp) + }) reg(3, opts.Config.AuthBasic.Service.Name, func(ctx context.Context, cfg *occfg.Config) error { cfg.AuthBasic.Context = ctx cfg.AuthBasic.Commons = cfg.Commons @@ -324,11 +327,6 @@ func NewService(ctx context.Context, options ...Option) (*Service, error) { cfg.Audit.Commons = cfg.Commons return audit.Execute(cfg.Audit) }) - areg(opts.Config.AuthApp.Service.Name, func(ctx context.Context, cfg *occfg.Config) error { - cfg.AuthApp.Context = ctx - cfg.AuthApp.Commons = cfg.Commons - return authapp.Execute(cfg.AuthApp) - }) areg(opts.Config.Policies.Service.Name, func(ctx context.Context, cfg *occfg.Config) error { cfg.Policies.Context = ctx cfg.Policies.Commons = cfg.Commons diff --git a/services/auth-app/README.md b/services/auth-app/README.md index 7aa045d11a..06c6ea6ddf 100644 --- a/services/auth-app/README.md +++ b/services/auth-app/README.md @@ -1,53 +1,44 @@ # Auth-App -The auth-app service provides authentication for 3rd party apps. +The auth-app service provides authentication for 3rd party apps unable to use +OpenID Connect. The service is enabled by default and started automatically. It +is possible to disable the service by setting: -## The `auth` Service Family - -OpenCloud uses serveral authentication services for different use cases. All services that start with `auth-` are part of the authentication service family. Each member authenticates requests with different scopes. As of now, these services exist: - - `auth-app` handles authentication of external 3rd party apps - - `auth-basic` handles basic authentication - - `auth-bearer` handles oidc authentication - - `auth-machine` handles interservice authentication when a user is impersonated - - `auth-service` handles interservice authentication when using service accounts - -## Service Startup - -Because this service is not started automatically, a manual start needs to be initiated which can be done in several ways. To configure the service usage, an environment variable for the proxy service needs to be set to allow app authentication. ```bash -OC_ADD_RUN_SERVICES=auth-app # deployment specific. Add the service to the manual startup list, use with binary deployments. Alternatively you can start the service explicitly via the command line. -PROXY_ENABLE_APP_AUTH=true # mandatory, allow app authentication. In case of a distributed environment, this envvar needs to be set in the proxy service. +OC_EXCLUDE_RUN_SERVICES=auth-app # deployment specific. Removes service from the list of automatically started services, use with single-binary deployments +PROXY_ENABLE_APP_AUTH=false # mandatory, disables app authentication. In case of a distributed environment, this envvar needs to be set in the proxy service. ``` ## App Tokens -App Tokens are used to authenticate 3rd party access via https like when using curl (apps) to access an API endpoint. These apps need to authenticate themselves as no logged in user authenticates the request. To be able to use an app token, one must first create a token. There are different options of creating a token. +App Tokens are password specifically generated to be used by 3rd party applications +for authentication when accessing the OpenCloud API endpoints. To +be able to use an app token, one must first create a token. There are different +options of creating a token. -### Via CLI (dev only) +## Important Security Note -Replace the `user-name` with an existing user. For the `token-expiration`, you can use any time abbreviation from the following list: `h, m, s`. Examples: `72h` or `1h` or `1m` or `1s.` Default is `72h`. +When using an external IDP for authentication, App Token are NOT invalidated +when the user is disabled or locked in that external IDP. That means the user +will still be able to use its existing App Tokens for authentication for as +long as the App Tokes are valid. -```bash -opencloud auth-app create --user-name={user-name} --expiration={token-expiration} -``` - -Once generated, these tokens can be used to authenticate requests to OpenCloud. They are passed as part of the request as `Basic Auth` header. +## Managing App Tokens ### Via API -The `auth-app` service provides an API to create (POST), list (GET) and delete (DELETE) tokens at the `/auth-app/tokens` endpoint. +Please note: This API is preliminary. In the future we will provide endpoints +in the `graph` service for allowing the management of App Tokens. -When using curl for the respective command, you need to authenticate with a header. To do so, get from the browsers developer console the currently active bearer token. Consider that this token has a short lifetime. In any example, replace `` with the URL:port of your OpenCloud instance, and `{token}` `{value}` accordingly. Note that the active bearer token authenticates the user the token was issued for. +The `auth-app` service provides an API to create (POST), list (GET) and delete (DELETE) tokens at the `/auth-app/tokens` endpoint. * **Create a token**\ The POST request requires: * A `expiry` key/value pair in the form of `expiry=`\ Example: `expiry=72h` - * An active bearer token ```bash curl --request POST 'https:///auth-app/tokens?expiry={value}' \ - --header 'accept: application/json' \ - --header 'authorization: Bearer {token}' + --header 'accept: application/json' ``` Example output: ``` @@ -59,14 +50,19 @@ When using curl for the respective command, you need to authenticate with a head } ``` + Note, that this is the only time the app token will be returned in cleartext. To use the token + please copy it from the response. + * **List tokens**\ - The GET request only requires an active bearer token for authentication:\ - Note that `--request GET` is technically not required because it is curl default. ```bash curl --request GET 'https:///auth-app/tokens' \ - --header 'accept: application/json' \ - --header 'authorization: Bearer {token}' + --header 'accept: application/json' ``` + + Note that the `token` value in the response to the "List Tokens` request is not the actual + app token, but a hashed value of the token. So this value cannot be used for authenticating + with the token. + Example output: ``` [ @@ -87,20 +83,23 @@ When using curl for the respective command, you need to authenticate with a head * **Delete a token**\ The DELETE request requires: - * A `token` key/value pair in the form of `token=`\ - Example: `token=Z3s2K7816M4vuSpd5` - * An active bearer token + * A `token` key/value pair in the form of `token=`. The value needs to be the hashed value as returned by the `List Tokens` respone.\ + Example: `token=$2$Z3s2K7816M4vuSpd5` ```bash curl --request DELETE 'https:///auth-app/tokens?token={value}' \ - --header 'accept: application/json' \ - --header 'authorization: Bearer {token}' + --header 'accept: application/json' ``` ### Via Impersonation API -When setting the environment variable `AUTH_APP_ENABLE_IMPERSONATION` to `true`, admins will be able to use the `/auth-app/tokens` endpoint to create tokens for other users but using their own bearer token for authentication. This can be important for migration scenarios, but should not be considered for regular tasks on a production system for security reasons. +When setting the environment variable `AUTH_APP_ENABLE_IMPERSONATION` to +`true`, admins will be able to use the `/auth-app/tokens` endpoint to create +tokens for other users. This can be important for migration scenarios, but +should not be considered for regular tasks on a production system for security +reasons. -To impersonate, the respective requests from the CLI commands above extend with the following parameters, where you can use one or the other: +To impersonate, the respective requests from the CLI commands above extend with +the following parameters, where you can use one or the other: * The `userID` in the form of: `userID={value}`\ Example:\ @@ -114,6 +113,27 @@ Example:\ A final create request would then look like: ```bash curl --request POST 'https:///auth-app/tokens?expiry={value}&userName={value}' \ - --header 'accept: application/json' \ - --header 'authorization: Bearer {token}' + --header 'accept: application/json' +``` + +### Via CLI (developer only) + +As the CLI is using the internal CS3Apis this needs access to the reva gateway +service. This is mainly of developer (and admin) usage. +Replace the `user-name` with an existing user. For the `token-expiration`, you +can use any time abbreviation from the following list: `h, m, s`. Examples: +`72h` or `1h` or `1m` or `1s.` Default is `72h`. + +```bash +opencloud auth-app create --user-name={user-name} --expiration={token-expiration} +``` + +## Authenticating using App Tokens + +To autenticate using an App Token simply use the username for which token was generated +and the token value as returned by the "Create Token" request. + +```bash +curl -u : 'https:///graph/v1.0/me' \ + --header 'accept: application/json' ``` diff --git a/services/auth-app/pkg/config/config.go b/services/auth-app/pkg/config/config.go index 4c65596752..656f0a4087 100644 --- a/services/auth-app/pkg/config/config.go +++ b/services/auth-app/pkg/config/config.go @@ -28,9 +28,40 @@ type Config struct { AllowImpersonation bool `yaml:"allow_impersonation" env:"AUTH_APP_ENABLE_IMPERSONATION" desc:"Allows admins to create app tokens for other users. Used for migration. Do NOT use in productive deployments." introductionVersion:"1.0.0"` + StorageDriver string `yaml:"storage_driver" env:"AUTH_APP_STORAGE_DRIVER" desc:"Driver to be used to persist the app tokes . Supported values are 'jsoncs3', 'json'." introductionVersion:"%%NEXT%%"` + StorageDrivers StorageDrivers `yaml:"storage_drivers"` + Context context.Context `yaml:"-"` } +type StorageDrivers struct { + JSONCS3 JSONCS3Driver `yaml:"jsoncs3"` +} + +type JSONCS3Driver struct { + ProviderAddr string `yaml:"provider_addr" env:"AUTH_APP_JSONCS3_PROVIDER_ADDR" desc:"GRPC address of the STORAGE-SYSTEM service." introductionVersion:"%%NEXT%%"` + SystemUserID string `yaml:"system_user_id" env:"OC_SYSTEM_USER_ID;AUTH_APP_JSONCS3_SYSTEM_USER_ID" desc:"ID of the OpenCloud STORAGE-SYSTEM system user. Admins need to set the ID for the STORAGE-SYSTEM system user in this config option which is then used to reference the user. Any reasonable long string is possible, preferably this would be an UUIDv4 format." introductionVersion:"%%NEXT%%"` + SystemUserIDP string `yaml:"system_user_idp" env:"OC_SYSTEM_USER_IDP;AUTH_APP_JSONCS3_SYSTEM_USER_IDP" desc:"IDP of the OpenCloud STORAGE-SYSTEM system user." introductionVersion:"%%NEXT%%"` + SystemUserAPIKey string `yaml:"system_user_api_key" env:"OC_SYSTEM_USER_API_KEY;AUTH_APP_JSONCS3_SYSTEM_USER_API_KEY" desc:"API key for the STORAGE-SYSTEM system user." introductionVersion:"%%NEXT%%"` + PasswordGenerator string `yaml:"password_generator" env:"AUTH_APP_JSONCS3_PASSWORD_GENERATOR" desc:"The password generator that should be used for generating app tokens. Supported values are: 'diceware' and 'random'." introductionVersion:"%%NEXT%%"` + PasswordGeneratorOptions PasswordGeneratorOptions `yaml:"password_generator_options"` +} + +type PasswordGeneratorOptions struct { + DicewareOptions DicewareOptions `yaml:"diceware"` + RandPWOpts RandPWOpts `yaml:"randon"` +} + +// DicewareOptions defines the config options for the "diceware" password generator +type DicewareOptions struct { + NumberOfWords int `yaml:"number_of_words" env:"AUTH_APP_JSONCS3_DICEWARE_NUMBER_OF_WORDS" desc:"The number of words the generated passphrase will have." introductionVersion:"%%NEXT%%"` +} + +// RandPWOpts defines the config options for the "random" password generator +type RandPWOpts struct { + PasswordLength int `yaml:"password_length" env:"AUTH_APP_JSONCS3_RANDOM_PASSWORD_LENGTH" desc:"The number of charactors the generated passwords will have." introductionVersion:"%%NEXT%%"` +} + // Log defines the loging configuration type Log struct { Level string `yaml:"level" env:"OC_LOG_LEVEL;AUTH_APP_LOG_LEVEL" desc:"The log level. Valid values are: 'panic', 'fatal', 'error', 'warn', 'info', 'debug', 'trace'." introductionVersion:"1.0.0"` diff --git a/services/auth-app/pkg/config/defaults/defaultconfig.go b/services/auth-app/pkg/config/defaults/defaultconfig.go index 0c726b05a3..d083dcdca0 100644 --- a/services/auth-app/pkg/config/defaults/defaultconfig.go +++ b/services/auth-app/pkg/config/defaults/defaultconfig.go @@ -44,6 +44,19 @@ func DefaultConfig() *config.Config { Service: config.Service{ Name: "auth-app", }, + StorageDriver: "jsoncs3", + StorageDrivers: config.StorageDrivers{ + JSONCS3: config.JSONCS3Driver{ + ProviderAddr: "eu.opencloud.api.storage-system", + SystemUserIDP: "internal", + PasswordGenerator: "diceware", + PasswordGeneratorOptions: config.PasswordGeneratorOptions{ + DicewareOptions: config.DicewareOptions{ + NumberOfWords: 6, + }, + }, + }, + }, Reva: shared.DefaultRevaConfig(), } } @@ -85,6 +98,14 @@ func EnsureDefaults(cfg *config.Config) { cfg.MachineAuthAPIKey = cfg.Commons.MachineAuthAPIKey } + if cfg.StorageDrivers.JSONCS3.SystemUserAPIKey == "" && cfg.Commons != nil && cfg.Commons.SystemUserAPIKey != "" { + cfg.StorageDrivers.JSONCS3.SystemUserAPIKey = cfg.Commons.SystemUserAPIKey + } + + if cfg.StorageDrivers.JSONCS3.SystemUserID == "" && cfg.Commons != nil && cfg.Commons.SystemUserID != "" { + cfg.StorageDrivers.JSONCS3.SystemUserID = cfg.Commons.SystemUserID + } + if cfg.TokenManager == nil && cfg.Commons != nil && cfg.Commons.TokenManager != nil { cfg.TokenManager = &config.TokenManager{ JWTSecret: cfg.Commons.TokenManager.JWTSecret, diff --git a/services/auth-app/pkg/revaconfig/config.go b/services/auth-app/pkg/revaconfig/config.go index 325e222b8f..9ee5386bb7 100644 --- a/services/auth-app/pkg/revaconfig/config.go +++ b/services/auth-app/pkg/revaconfig/config.go @@ -11,6 +11,14 @@ import ( func AuthAppConfigFromStruct(cfg *config.Config) map[string]interface{} { appAuthJSON := filepath.Join(defaults.BaseDataPath(), "appauth.json") + jsonCS3pwGenOpt := map[string]any{} + switch cfg.StorageDrivers.JSONCS3.PasswordGenerator { + case "random": + jsonCS3pwGenOpt["token_strength"] = cfg.StorageDrivers.JSONCS3.PasswordGeneratorOptions.RandPWOpts.PasswordLength + case "diceware": + jsonCS3pwGenOpt["number_of_words"] = cfg.StorageDrivers.JSONCS3.PasswordGeneratorOptions.DicewareOptions.NumberOfWords + } + rcfg := map[string]interface{}{ "shared": map[string]interface{}{ "jwt_secret": cfg.TokenManager.JWTSecret, @@ -36,11 +44,19 @@ func AuthAppConfigFromStruct(cfg *config.Config) map[string]interface{} { }, }, "applicationauth": map[string]interface{}{ - "driver": "json", + "driver": cfg.StorageDriver, "drivers": map[string]interface{}{ "json": map[string]interface{}{ "file": appAuthJSON, }, + "jsoncs3": map[string]interface{}{ + "provider_addr": cfg.StorageDrivers.JSONCS3.ProviderAddr, + "service_user_id": cfg.StorageDrivers.JSONCS3.SystemUserID, + "service_user_idp": cfg.StorageDrivers.JSONCS3.SystemUserIDP, + "machine_auth_apikey": cfg.StorageDrivers.JSONCS3.SystemUserAPIKey, + "password_generator": cfg.StorageDrivers.JSONCS3.PasswordGenerator, + "generator_config": jsonCS3pwGenOpt, + }, }, }, }, diff --git a/services/auth-app/pkg/service/service.go b/services/auth-app/pkg/service/service.go index 613c42eb3a..753d65f6f2 100644 --- a/services/auth-app/pkg/service/service.go +++ b/services/auth-app/pkg/service/service.go @@ -99,7 +99,10 @@ func (a *AuthAppService) HandleCreate(w http.ResponseWriter, r *http.Request) { return } - label := "Generated via API" + label := q.Get("label") + if label == "" { + label = "Generated via API" + } // Impersonated request userID, userName := q.Get("userID"), q.Get("userName") @@ -131,7 +134,7 @@ func (a *AuthAppService) HandleCreate(w http.ResponseWriter, r *http.Request) { return } - label = "Generated via Impersonation API" + label = label + " (Impersonation)" } scopes, err := scope.AddOwnerScope(map[string]*authpb.Scope{}) diff --git a/services/proxy/pkg/command/server.go b/services/proxy/pkg/command/server.go index 799bbd1b97..035af7f006 100644 --- a/services/proxy/pkg/command/server.go +++ b/services/proxy/pkg/command/server.go @@ -352,7 +352,7 @@ func loadMiddlewares(logger log.Logger, cfg *config.Config, middleware.CredentialsByUserAgent(cfg.AuthMiddleware.CredentialsByUserAgent), middleware.Logger(logger), middleware.OIDCIss(cfg.OIDC.Issuer), - middleware.EnableBasicAuth(cfg.EnableBasicAuth), + middleware.EnableBasicAuth(cfg.EnableBasicAuth || cfg.AuthMiddleware.AllowAppAuth), middleware.TraceProvider(traceProvider), ), middleware.AccountResolver( diff --git a/services/proxy/pkg/config/defaults/defaultconfig.go b/services/proxy/pkg/config/defaults/defaultconfig.go index 5a8fc9246a..f1d42a3f8f 100644 --- a/services/proxy/pkg/config/defaults/defaultconfig.go +++ b/services/proxy/pkg/config/defaults/defaultconfig.go @@ -100,6 +100,9 @@ func DefaultConfig() *config.Config { Cluster: "opencloud-cluster", EnableTLS: false, }, + AuthMiddleware: config.AuthMiddleware{ + AllowAppAuth: true, + }, } } diff --git a/vendor/github.com/opencloud-eu/reva/v2/pkg/appauth/manager/jsoncs3/jsoncs3.go b/vendor/github.com/opencloud-eu/reva/v2/pkg/appauth/manager/jsoncs3/jsoncs3.go index 2cbe9450b7..9ffc0de7cf 100644 --- a/vendor/github.com/opencloud-eu/reva/v2/pkg/appauth/manager/jsoncs3/jsoncs3.go +++ b/vendor/github.com/opencloud-eu/reva/v2/pkg/appauth/manager/jsoncs3/jsoncs3.go @@ -226,6 +226,15 @@ func (m *manager) InvalidateAppPassword(ctx context.Context, secret string) erro updater := func(a map[string]*apppb.AppPassword) (map[string]*apppb.AppPassword, error) { for key, pw := range a { + // Allow deleting a token using the password hash. This is needed because of + // some shortcomings of the CS3 APIs. On the API level tokens don't have IDs + // ListAppPasswords only returns the hashed password. So allowing to delete + // using the hashed password as the key is the only way to delete tokens for + // which the user does not remember the password. + if secret == pw.Password { + delete(a, key) + return a, nil + } ok, err := argon2id.ComparePasswordAndHash(secret, pw.Password) switch { case err != nil: diff --git a/vendor/modules.txt b/vendor/modules.txt index 4480d4486f..cb06c3a90f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1191,7 +1191,7 @@ github.com/open-policy-agent/opa/v1/types github.com/open-policy-agent/opa/v1/util github.com/open-policy-agent/opa/v1/util/decoding github.com/open-policy-agent/opa/v1/version -# github.com/opencloud-eu/reva/v2 v2.28.1-0.20250320105919-be91238e6b11 +# github.com/opencloud-eu/reva/v2 v2.28.1-0.20250320135948-a946c0d6d289 ## explicit; go 1.24.1 github.com/opencloud-eu/reva/v2/cmd/revad/internal/grace github.com/opencloud-eu/reva/v2/cmd/revad/runtime