add public share auth middleware
This commit is contained in:
@@ -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
|
||||||
+16
-12
@@ -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)
|
rolesClient := settings.NewRoleService("com.owncloud.api.settings", grpc.DefaultClient)
|
||||||
revaClient, err := cs3.GetGatewayServiceClient(cfg.Reva.Address)
|
revaClient, err := cs3.GetGatewayServiceClient(cfg.Reva.Address)
|
||||||
var userProvider backend.UserBackend
|
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),
|
"expires": int64(24 * 60 * 60),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Error().Err(err).
|
logger.Error().Err(err).
|
||||||
Msg("Failed to create token manager")
|
Msg("Failed to create token manager")
|
||||||
}
|
}
|
||||||
userProvider = backend.NewAccountsServiceUserBackend(
|
userProvider = backend.NewAccountsServiceUserBackend(
|
||||||
@@ -166,17 +166,17 @@ func loadMiddlewares(ctx context.Context, l log.Logger, cfg *config.Config) alic
|
|||||||
rolesClient,
|
rolesClient,
|
||||||
cfg.OIDC.Issuer,
|
cfg.OIDC.Issuer,
|
||||||
tokenManager,
|
tokenManager,
|
||||||
l,
|
logger,
|
||||||
)
|
)
|
||||||
case "cs3":
|
case "cs3":
|
||||||
userProvider = backend.NewCS3UserBackend(rolesClient, revaClient, cfg.MachineAuthAPIKey, l)
|
userProvider = backend.NewCS3UserBackend(rolesClient, revaClient, cfg.MachineAuthAPIKey, logger)
|
||||||
default:
|
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)
|
storeClient := storepb.NewStoreService("com.owncloud.api.store", grpc.DefaultClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Error().Err(err).
|
logger.Error().Err(err).
|
||||||
Str("gateway", cfg.Reva.Address).
|
Str("gateway", cfg.Reva.Address).
|
||||||
Msg("Failed to create reva gateway service client")
|
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,
|
pkgmiddleware.TraceContext,
|
||||||
chimiddleware.RealIP,
|
chimiddleware.RealIP,
|
||||||
chimiddleware.RequestID,
|
chimiddleware.RequestID,
|
||||||
middleware.AccessLog(l),
|
middleware.AccessLog(logger),
|
||||||
middleware.HTTPSRedirect,
|
middleware.HTTPSRedirect,
|
||||||
|
|
||||||
// now that we established the basics, on with authentication middleware
|
// now that we established the basics, on with authentication middleware
|
||||||
@@ -216,20 +216,24 @@ func loadMiddlewares(ctx context.Context, l log.Logger, cfg *config.Config) alic
|
|||||||
middleware.TokenCacheTTL(time.Second*time.Duration(cfg.OIDC.UserinfoCache.TTL)),
|
middleware.TokenCacheTTL(time.Second*time.Duration(cfg.OIDC.UserinfoCache.TTL)),
|
||||||
|
|
||||||
// basic Options
|
// basic Options
|
||||||
middleware.Logger(l),
|
middleware.Logger(logger),
|
||||||
middleware.EnableBasicAuth(cfg.EnableBasicAuth),
|
middleware.EnableBasicAuth(cfg.EnableBasicAuth),
|
||||||
middleware.UserProvider(userProvider),
|
middleware.UserProvider(userProvider),
|
||||||
middleware.OIDCIss(cfg.OIDC.Issuer),
|
middleware.OIDCIss(cfg.OIDC.Issuer),
|
||||||
middleware.CredentialsByUserAgent(cfg.Reva.Middleware.Auth.CredentialsByUserAgent),
|
middleware.CredentialsByUserAgent(cfg.Reva.Middleware.Auth.CredentialsByUserAgent),
|
||||||
),
|
),
|
||||||
|
middleware.PublicShareAuth(
|
||||||
|
middleware.Logger(logger),
|
||||||
|
middleware.RevaGatewayClient(revaClient),
|
||||||
|
),
|
||||||
middleware.SignedURLAuth(
|
middleware.SignedURLAuth(
|
||||||
middleware.Logger(l),
|
middleware.Logger(logger),
|
||||||
middleware.PreSignedURLConfig(cfg.PreSignedURL),
|
middleware.PreSignedURLConfig(cfg.PreSignedURL),
|
||||||
middleware.UserProvider(userProvider),
|
middleware.UserProvider(userProvider),
|
||||||
middleware.Store(storeClient),
|
middleware.Store(storeClient),
|
||||||
),
|
),
|
||||||
middleware.AccountResolver(
|
middleware.AccountResolver(
|
||||||
middleware.Logger(l),
|
middleware.Logger(logger),
|
||||||
middleware.UserProvider(userProvider),
|
middleware.UserProvider(userProvider),
|
||||||
middleware.TokenManagerConfig(cfg.TokenManager),
|
middleware.TokenManagerConfig(cfg.TokenManager),
|
||||||
middleware.UserOIDCClaim(cfg.UserOIDCClaim),
|
middleware.UserOIDCClaim(cfg.UserOIDCClaim),
|
||||||
@@ -238,14 +242,14 @@ func loadMiddlewares(ctx context.Context, l log.Logger, cfg *config.Config) alic
|
|||||||
),
|
),
|
||||||
|
|
||||||
middleware.SelectorCookie(
|
middleware.SelectorCookie(
|
||||||
middleware.Logger(l),
|
middleware.Logger(logger),
|
||||||
middleware.UserProvider(userProvider),
|
middleware.UserProvider(userProvider),
|
||||||
middleware.PolicySelectorConfig(*cfg.PolicySelector),
|
middleware.PolicySelectorConfig(*cfg.PolicySelector),
|
||||||
),
|
),
|
||||||
|
|
||||||
// finally, trigger home creation when a user logs in
|
// finally, trigger home creation when a user logs in
|
||||||
middleware.CreateHome(
|
middleware.CreateHome(
|
||||||
middleware.Logger(l),
|
middleware.Logger(logger),
|
||||||
middleware.TokenManagerConfig(cfg.TokenManager),
|
middleware.TokenManagerConfig(cfg.TokenManager),
|
||||||
middleware.RevaGatewayClient(revaClient),
|
middleware.RevaGatewayClient(revaClient),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
headerRevaAccessToken = "x-access-token"
|
||||||
|
headerShareToken = "public-token"
|
||||||
|
appProviderPathPrefix = "/app/open"
|
||||||
|
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 == "" || !strings.HasPrefix(appProviderPathPrefix, r.URL.Path) {
|
||||||
|
// 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