mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-24 22:08:58 -05:00
reva tries to avoid copying proto messages now. This changed some calls to take pointers now (mainly e.g. FormatResourceId())
204 lines
7.4 KiB
Go
204 lines
7.4 KiB
Go
package middleware
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"time"
|
|
|
|
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
|
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
|
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
|
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
|
|
"github.com/golang-jwt/jwt/v4"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
|
"github.com/owncloud/ocis/v2/ocis-pkg/oidc"
|
|
oidcmocks "github.com/owncloud/ocis/v2/ocis-pkg/oidc/mocks"
|
|
"github.com/owncloud/ocis/v2/services/proxy/pkg/router"
|
|
"github.com/owncloud/ocis/v2/services/proxy/pkg/user/backend"
|
|
"github.com/owncloud/ocis/v2/services/proxy/pkg/user/backend/mocks"
|
|
"github.com/stretchr/testify/mock"
|
|
"go-micro.dev/v4/store"
|
|
"google.golang.org/grpc"
|
|
)
|
|
|
|
var _ = Describe("authentication helpers", func() {
|
|
DescribeTable("isPublicPath should recognize public paths",
|
|
func(input string, expected bool) {
|
|
isPublic := isPublicPath(input)
|
|
Expect(isPublic).To(Equal(expected))
|
|
},
|
|
Entry("public files path", "/remote.php/dav/public-files/", true),
|
|
Entry("public files path without remote.php", "/remote.php/dav/public-files/", true),
|
|
Entry("token info path", "/ocs/v1.php/apps/files_sharing/api/v1/tokeninfo/unprotected", true),
|
|
Entry("token info path", "/ocs/v2.php/apps/files_sharing/api/v1/tokeninfo/unprotected", true),
|
|
Entry("capabilities", "/ocs/v1.php/cloud/capabilities", true),
|
|
)
|
|
})
|
|
|
|
var _ = Describe("Authenticating requests", Label("Authentication"), func() {
|
|
var (
|
|
authenticators []Authenticator
|
|
)
|
|
oc := oidcmocks.OIDCClient{}
|
|
oc.On("VerifyAccessToken", mock.Anything, mock.Anything).Return(
|
|
oidc.RegClaimsWithSID{
|
|
SessionID: "a-session-id",
|
|
RegisteredClaims: jwt.RegisteredClaims{
|
|
ExpiresAt: jwt.NewNumericDate(time.Unix(1147483647, 0)),
|
|
},
|
|
}, jwt.MapClaims{
|
|
"sid": "a-session-id",
|
|
"exp": 1147483647,
|
|
},
|
|
nil,
|
|
)
|
|
|
|
ub := mocks.UserBackend{}
|
|
ub.On("Authenticate", mock.Anything, "testuser", "testpassword").Return(
|
|
&userv1beta1.User{
|
|
Id: &userv1beta1.UserId{
|
|
Idp: "IdpId",
|
|
OpaqueId: "OpaqueId",
|
|
},
|
|
Username: "testuser",
|
|
Mail: "testuser@example.com",
|
|
},
|
|
"",
|
|
nil,
|
|
)
|
|
ub.On("Authenticate", mock.Anything, mock.Anything, mock.Anything).Return(nil, "", backend.ErrAccountNotFound)
|
|
|
|
BeforeEach(func() {
|
|
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
|
|
|
|
logger := log.NewLogger()
|
|
authenticators = []Authenticator{
|
|
BasicAuthenticator{
|
|
Logger: logger,
|
|
UserProvider: &ub,
|
|
},
|
|
&OIDCAuthenticator{
|
|
OIDCIss: "http://idp.example.com",
|
|
Logger: logger,
|
|
oidcClient: &oc,
|
|
userInfoCache: store.NewMemoryStore(),
|
|
skipUserInfo: true,
|
|
},
|
|
PublicShareAuthenticator{
|
|
Logger: logger,
|
|
RevaGatewaySelector: pool.GetSelector[gateway.GatewayAPIClient](
|
|
"GatewaySelector",
|
|
"com.owncloud.api.gateway",
|
|
func(cc grpc.ClientConnInterface) gateway.GatewayAPIClient {
|
|
return mockGatewayClient{
|
|
AuthenticateFunc: func(authType, clientID, clientSecret string) (string, rpcv1beta1.Code) {
|
|
if authType != "publicshares" {
|
|
return "", rpcv1beta1.Code_CODE_NOT_FOUND
|
|
}
|
|
|
|
if clientID == "sharetoken" && (clientSecret == "password|examples3cr3t" || clientSecret == "signature|examplesignature|exampleexpiration") {
|
|
return "exampletoken", rpcv1beta1.Code_CODE_OK
|
|
}
|
|
|
|
if clientID == "sharetoken" && clientSecret == "password|" {
|
|
return "otherexampletoken", rpcv1beta1.Code_CODE_OK
|
|
}
|
|
|
|
return "", rpcv1beta1.Code_CODE_NOT_FOUND
|
|
},
|
|
}
|
|
},
|
|
),
|
|
},
|
|
}
|
|
})
|
|
|
|
When("the public request must contains correct data", func() {
|
|
It("ensures the context oidc data when the Bearer authentication is successful", func() {
|
|
req := httptest.NewRequest("PROPFIND", "http://example.com/remote.php/dav/public-files/", http.NoBody)
|
|
req = req.WithContext(router.SetRoutingInfo(context.Background(), router.RoutingInfo{}))
|
|
req.Header.Set(_headerAuthorization, "Bearer jwt.token.sig")
|
|
|
|
handler := Authentication(authenticators,
|
|
EnableBasicAuth(true),
|
|
)
|
|
testHandler := handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
Expect(oidc.FromContext(r.Context())).To(Equal(map[string]interface{}{
|
|
"sid": "a-session-id",
|
|
"exp": int64(1147483647),
|
|
}))
|
|
}))
|
|
rr := httptest.NewRecorder()
|
|
testHandler.ServeHTTP(rr, req)
|
|
Expect(rr).To(HaveHTTPStatus(http.StatusOK))
|
|
})
|
|
It("ensures the context oidc data when user the Basic authentication is successful", func() {
|
|
req := httptest.NewRequest("PROPFIND", "http://example.com/remote.php/dav/public-files/", http.NoBody)
|
|
req = req.WithContext(router.SetRoutingInfo(context.Background(), router.RoutingInfo{}))
|
|
req.SetBasicAuth("testuser", "testpassword")
|
|
|
|
handler := Authentication(authenticators,
|
|
EnableBasicAuth(true),
|
|
)
|
|
testHandler := handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
Expect(oidc.FromContext(r.Context())).To(Equal(map[string]interface{}{
|
|
"email": "testuser@example.com",
|
|
"ownclouduuid": "OpaqueId",
|
|
"iss": "IdpId",
|
|
"preferred_username": "testuser",
|
|
}))
|
|
}))
|
|
rr := httptest.NewRecorder()
|
|
testHandler.ServeHTTP(rr, req)
|
|
Expect(rr).To(HaveHTTPStatus(http.StatusOK))
|
|
})
|
|
It("ensures the x-access-token header when public-token URL parameter is set", func() {
|
|
req := httptest.NewRequest("PROPFIND", "http://example.com/dav/public-files/?public-token=sharetoken", http.NoBody)
|
|
req = req.WithContext(router.SetRoutingInfo(context.Background(), router.RoutingInfo{}))
|
|
|
|
handler := Authentication(authenticators,
|
|
EnableBasicAuth(true),
|
|
)
|
|
testHandler := handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
Expect(r.Header.Get(_headerRevaAccessToken)).To(Equal("otherexampletoken"))
|
|
}))
|
|
rr := httptest.NewRecorder()
|
|
testHandler.ServeHTTP(rr, req)
|
|
Expect(rr).To(HaveHTTPStatus(http.StatusOK))
|
|
})
|
|
It("ensures the x-access-token header when public-token URL parameter and BasicAuth are set", func() {
|
|
req := httptest.NewRequest("PROPFIND", "http://example.com/dav/public-files/?public-token=sharetoken", http.NoBody)
|
|
req.SetBasicAuth("public", "examples3cr3t")
|
|
req = req.WithContext(router.SetRoutingInfo(context.Background(), router.RoutingInfo{}))
|
|
|
|
handler := Authentication(authenticators,
|
|
EnableBasicAuth(true),
|
|
)
|
|
testHandler := handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
Expect(r.Header.Get(_headerRevaAccessToken)).To(Equal("exampletoken"))
|
|
}))
|
|
rr := httptest.NewRecorder()
|
|
testHandler.ServeHTTP(rr, req)
|
|
Expect(rr).To(HaveHTTPStatus(http.StatusOK))
|
|
})
|
|
It("ensures the x-access-token header when public-token BasicAuth is set", func() {
|
|
req := httptest.NewRequest("GET", "http://example.com/archiver", http.NoBody)
|
|
req.Header.Set("public-token", "sharetoken")
|
|
req = req.WithContext(router.SetRoutingInfo(context.Background(), router.RoutingInfo{}))
|
|
|
|
handler := Authentication(authenticators,
|
|
EnableBasicAuth(true),
|
|
)
|
|
testHandler := handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
Expect(r.Header.Get(_headerRevaAccessToken)).To(Equal("otherexampletoken"))
|
|
}))
|
|
rr := httptest.NewRecorder()
|
|
testHandler.ServeHTTP(rr, req)
|
|
Expect(rr).To(HaveHTTPStatus(http.StatusOK))
|
|
})
|
|
})
|
|
})
|