mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-30 17:00:57 -06:00
Merge pull request #2536 from owncloud/public-share-auth-middleware
add public share auth middleware
This commit is contained in:
6
changelog/unreleased/public-share-auth-middleware.md
Normal file
6
changelog/unreleased/public-share-auth-middleware.md
Normal file
@@ -0,0 +1,6 @@
|
||||
Enhancement: Add a middleware to authenticate public share requests
|
||||
|
||||
Added a new middleware to authenticate public share requests. This makes it possible to use APIs which require an authenticated context with public shares.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/2536
|
||||
https://github.com/owncloud/ocis/issues/2479
|
||||
10
changelog/unreleased/update-reva.md
Normal file
10
changelog/unreleased/update-reva.md
Normal file
@@ -0,0 +1,10 @@
|
||||
Enhancement: Update reva to v1.14.1-0.20211015144112-cddbdd4c560f
|
||||
|
||||
Updated reva to v1.14.1-0.20211015144112-cddbdd4c560f
|
||||
This update includes:
|
||||
* Enhancement [cs3org/reva#2170](https://github.com/cs3org/reva/pull/2170): Handle propfind requests for existing files
|
||||
* Enhancement [cs3org/reva#2166](https://github.com/cs3org/reva/pull/2166): Allow nil quota in decomposedfs
|
||||
* Enhancement [cs3org/reva#2152](https://github.com/cs3org/reva/pull/2152): Report quota per storage space
|
||||
* Enhancement [cs3org/reva#2143](https://github.com/cs3org/reva/pull/2143): Enabling apps to work in public shares
|
||||
|
||||
https://github.com/owncloud/ocis/pull/2536
|
||||
2
go.mod
2
go.mod
@@ -19,7 +19,7 @@ require (
|
||||
github.com/blevesearch/bleve/v2 v2.1.0
|
||||
github.com/coreos/go-oidc/v3 v3.0.0
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20211007101428-6d142794ec11
|
||||
github.com/cs3org/reva v1.14.1-0.20211015081146-2e9bc0c7714a
|
||||
github.com/cs3org/reva v1.14.1-0.20211015144112-cddbdd4c560f
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/glauth/glauth v1.1.3-0.20210729125545-b9aecdfcac31
|
||||
github.com/go-chi/chi/v5 v5.0.4
|
||||
|
||||
2
go.sum
2
go.sum
@@ -292,6 +292,8 @@ github.com/cs3org/go-cs3apis v0.0.0-20211007101428-6d142794ec11 h1:cc/8fdzWdr/wA
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20211007101428-6d142794ec11/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
|
||||
github.com/cs3org/reva v1.14.1-0.20211015081146-2e9bc0c7714a h1:xauop9DkHYtOA3qLGmohOi0rt6WqN8+1BCWu5i/4cL4=
|
||||
github.com/cs3org/reva v1.14.1-0.20211015081146-2e9bc0c7714a/go.mod h1:uENdZEtDFmTRt6+d4+Ro4P5XnNL+9I6gwftHEBJzHQw=
|
||||
github.com/cs3org/reva v1.14.1-0.20211015144112-cddbdd4c560f h1:DVy9daUTEgnAP35Q5Vn5rt0FXiHwTr4vp0pecHFHA4Q=
|
||||
github.com/cs3org/reva v1.14.1-0.20211015144112-cddbdd4c560f/go.mod h1:uENdZEtDFmTRt6+d4+Ro4P5XnNL+9I6gwftHEBJzHQw=
|
||||
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
|
||||
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
|
||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||
|
||||
@@ -61,7 +61,7 @@ func Auth(opts ...account.Option) func(http.Handler) http.Handler {
|
||||
errorcode.InvalidAuthenticationToken.Render(w, r, http.StatusUnauthorized, "invalid token")
|
||||
return
|
||||
}
|
||||
if ok, err := scope.VerifyScope(tokenScope, r); err != nil || !ok {
|
||||
if ok, err := scope.VerifyScope(ctx, tokenScope, r); err != nil || !ok {
|
||||
opt.Logger.Error().Err(err).Msg("verifying scope failed")
|
||||
errorcode.InvalidAuthenticationToken.Render(w, r, http.StatusUnauthorized, "verifying scope failed")
|
||||
return
|
||||
|
||||
@@ -60,7 +60,7 @@ func ExtractAccountUUID(opts ...account.Option) func(http.Handler) http.Handler
|
||||
opt.Logger.Error().Err(err)
|
||||
return
|
||||
}
|
||||
if ok, err := scope.VerifyScope(tokenScope, r); err != nil || !ok {
|
||||
if ok, err := scope.VerifyScope(r.Context(), tokenScope, r); err != nil || !ok {
|
||||
opt.Logger.Error().Err(err).Msg("verifying scope failed")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ func Server(cfg *config.Config) *cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func loadMiddlewares(ctx context.Context, l log.Logger, cfg *config.Config) alice.Chain {
|
||||
func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config) alice.Chain {
|
||||
rolesClient := settings.NewRoleService("com.owncloud.api.settings", grpc.DefaultClient)
|
||||
revaClient, err := cs3.GetGatewayServiceClient(cfg.Reva.Address)
|
||||
var userProvider backend.UserBackend
|
||||
@@ -158,7 +158,7 @@ func loadMiddlewares(ctx context.Context, l log.Logger, cfg *config.Config) alic
|
||||
"expires": int64(24 * 60 * 60),
|
||||
})
|
||||
if err != nil {
|
||||
l.Error().Err(err).
|
||||
logger.Error().Err(err).
|
||||
Msg("Failed to create token manager")
|
||||
}
|
||||
userProvider = backend.NewAccountsServiceUserBackend(
|
||||
@@ -166,17 +166,17 @@ func loadMiddlewares(ctx context.Context, l log.Logger, cfg *config.Config) alic
|
||||
rolesClient,
|
||||
cfg.OIDC.Issuer,
|
||||
tokenManager,
|
||||
l,
|
||||
logger,
|
||||
)
|
||||
case "cs3":
|
||||
userProvider = backend.NewCS3UserBackend(rolesClient, revaClient, cfg.MachineAuthAPIKey, l)
|
||||
userProvider = backend.NewCS3UserBackend(rolesClient, revaClient, cfg.MachineAuthAPIKey, logger)
|
||||
default:
|
||||
l.Fatal().Msgf("Invalid accounts backend type '%s'", cfg.AccountBackend)
|
||||
logger.Fatal().Msgf("Invalid accounts backend type '%s'", cfg.AccountBackend)
|
||||
}
|
||||
|
||||
storeClient := storepb.NewStoreService("com.owncloud.api.store", grpc.DefaultClient)
|
||||
if err != nil {
|
||||
l.Error().Err(err).
|
||||
logger.Error().Err(err).
|
||||
Str("gateway", cfg.Reva.Address).
|
||||
Msg("Failed to create reva gateway service client")
|
||||
}
|
||||
@@ -196,7 +196,7 @@ func loadMiddlewares(ctx context.Context, l log.Logger, cfg *config.Config) alic
|
||||
pkgmiddleware.TraceContext,
|
||||
chimiddleware.RealIP,
|
||||
chimiddleware.RequestID,
|
||||
middleware.AccessLog(l),
|
||||
middleware.AccessLog(logger),
|
||||
middleware.HTTPSRedirect,
|
||||
|
||||
// now that we established the basics, on with authentication middleware
|
||||
@@ -216,20 +216,20 @@ func loadMiddlewares(ctx context.Context, l log.Logger, cfg *config.Config) alic
|
||||
middleware.TokenCacheTTL(time.Second*time.Duration(cfg.OIDC.UserinfoCache.TTL)),
|
||||
|
||||
// basic Options
|
||||
middleware.Logger(l),
|
||||
middleware.Logger(logger),
|
||||
middleware.EnableBasicAuth(cfg.EnableBasicAuth),
|
||||
middleware.UserProvider(userProvider),
|
||||
middleware.OIDCIss(cfg.OIDC.Issuer),
|
||||
middleware.CredentialsByUserAgent(cfg.Reva.Middleware.Auth.CredentialsByUserAgent),
|
||||
),
|
||||
middleware.SignedURLAuth(
|
||||
middleware.Logger(l),
|
||||
middleware.Logger(logger),
|
||||
middleware.PreSignedURLConfig(cfg.PreSignedURL),
|
||||
middleware.UserProvider(userProvider),
|
||||
middleware.Store(storeClient),
|
||||
),
|
||||
middleware.AccountResolver(
|
||||
middleware.Logger(l),
|
||||
middleware.Logger(logger),
|
||||
middleware.UserProvider(userProvider),
|
||||
middleware.TokenManagerConfig(cfg.TokenManager),
|
||||
middleware.UserOIDCClaim(cfg.UserOIDCClaim),
|
||||
@@ -238,17 +238,21 @@ func loadMiddlewares(ctx context.Context, l log.Logger, cfg *config.Config) alic
|
||||
),
|
||||
|
||||
middleware.SelectorCookie(
|
||||
middleware.Logger(l),
|
||||
middleware.Logger(logger),
|
||||
middleware.UserProvider(userProvider),
|
||||
middleware.PolicySelectorConfig(*cfg.PolicySelector),
|
||||
),
|
||||
|
||||
// finally, trigger home creation when a user logs in
|
||||
middleware.CreateHome(
|
||||
middleware.Logger(l),
|
||||
middleware.Logger(logger),
|
||||
middleware.TokenManagerConfig(cfg.TokenManager),
|
||||
middleware.RevaGatewayClient(revaClient),
|
||||
),
|
||||
middleware.PublicShareAuth(
|
||||
middleware.Logger(logger),
|
||||
middleware.RevaGatewayClient(revaClient),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
56
proxy/pkg/middleware/public_share_auth.go
Normal file
56
proxy/pkg/middleware/public_share_auth.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
)
|
||||
|
||||
const (
|
||||
headerRevaAccessToken = "x-access-token"
|
||||
headerShareToken = "public-token"
|
||||
basicAuthPasswordPrefix = "basic|"
|
||||
authenticationType = "publicshares"
|
||||
)
|
||||
|
||||
// PublicShareAuth ...
|
||||
func PublicShareAuth(opts ...Option) func(next http.Handler) http.Handler {
|
||||
options := newOptions(opts...)
|
||||
logger := options.Logger
|
||||
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Currently we only want to authenticate app open request coming from public shares.
|
||||
shareToken := r.Header.Get(headerShareToken)
|
||||
if shareToken == "" {
|
||||
// Don't authenticate
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// We can ignore the username since it is always set to "public" in public shares.
|
||||
_, password, ok := r.BasicAuth()
|
||||
|
||||
sharePassword := basicAuthPasswordPrefix
|
||||
if ok {
|
||||
sharePassword += password
|
||||
}
|
||||
|
||||
authResp, err := options.RevaGatewayClient.Authenticate(r.Context(), &gateway.AuthenticateRequest{
|
||||
Type: authenticationType,
|
||||
ClientId: shareToken,
|
||||
ClientSecret: sharePassword,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logger.Debug().Err(err).Str("public_share_token", shareToken).Msg("could not authenticate public share")
|
||||
// try another middleware
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
r.Header.Add(headerRevaAccessToken, authResp.Token)
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user