github.com/cs3org/reva/v2@v2.27.7/internal/grpc/services/gateway/authprovider.go (about) 1 // Copyright 2018-2021 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package gateway 20 21 import ( 22 "context" 23 "fmt" 24 25 authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1" 26 registry "github.com/cs3org/go-cs3apis/cs3/auth/registry/v1beta1" 27 gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" 28 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 29 rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" 30 storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 31 "github.com/cs3org/reva/v2/pkg/appctx" 32 ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" 33 "github.com/cs3org/reva/v2/pkg/errtypes" 34 "github.com/cs3org/reva/v2/pkg/rgrpc/status" 35 "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" 36 "github.com/cs3org/reva/v2/pkg/sharedconf" 37 "github.com/pkg/errors" 38 "google.golang.org/grpc/metadata" 39 "google.golang.org/protobuf/proto" 40 ) 41 42 func (s *svc) Authenticate(ctx context.Context, req *gateway.AuthenticateRequest) (*gateway.AuthenticateResponse, error) { 43 log := appctx.GetLogger(ctx) 44 45 // find auth provider 46 c, err := s.findAuthProvider(ctx, req.Type) 47 if err != nil { 48 log.Err(err).Str("type", req.Type).Msg("error getting auth provider client") 49 return &gateway.AuthenticateResponse{ 50 Status: status.NewInternal(ctx, "error getting auth provider client"), 51 }, nil 52 } 53 54 authProviderReq := &authpb.AuthenticateRequest{ 55 ClientId: req.ClientId, 56 ClientSecret: req.ClientSecret, 57 } 58 res, err := c.Authenticate(ctx, authProviderReq) 59 switch { 60 case err != nil: 61 return &gateway.AuthenticateResponse{ 62 Status: status.NewInternal(ctx, fmt.Sprintf("gateway: error calling Authenticate for type: %s", req.Type)), 63 }, nil 64 case res.Status.Code == rpc.Code_CODE_PERMISSION_DENIED: 65 fallthrough 66 case res.Status.Code == rpc.Code_CODE_UNAUTHENTICATED: 67 fallthrough 68 case res.Status.Code == rpc.Code_CODE_NOT_FOUND: 69 // normal failures, no need to log 70 return &gateway.AuthenticateResponse{ 71 Status: res.Status, 72 }, nil 73 case res.Status.Code != rpc.Code_CODE_OK: 74 return &gateway.AuthenticateResponse{ 75 Status: status.NewInternal(ctx, fmt.Sprintf("error authenticating credentials to auth provider for type: %s", req.Type)), 76 }, nil 77 } 78 79 // validate valid userId 80 if res.User == nil { 81 err := errtypes.NotFound("gateway: user after Authenticate is nil") 82 log.Err(err).Msg("user is nil") 83 return &gateway.AuthenticateResponse{ 84 Status: status.NewInternal(ctx, "user is nil"), 85 }, nil 86 } 87 88 if res.User.Id == nil { 89 err := errtypes.NotFound("gateway: uid after Authenticate is nil") 90 log.Err(err).Msg("user id is nil") 91 return &gateway.AuthenticateResponse{ 92 Status: status.NewInternal(ctx, "user id is nil"), 93 }, nil 94 } 95 96 u := proto.Clone(res.User).(*userpb.User) 97 if sharedconf.SkipUserGroupsInToken() { 98 u.Groups = []string{} 99 } 100 101 token, err := s.tokenmgr.MintToken(ctx, u, res.TokenScope) 102 if err != nil { 103 err = errors.Wrap(err, "authsvc: error in MintToken") 104 res := &gateway.AuthenticateResponse{ 105 Status: status.NewUnauthenticated(ctx, err, "error creating access token"), 106 } 107 return res, nil 108 } 109 110 if scope, ok := res.TokenScope["user"]; s.c.DisableHomeCreationOnLogin || !ok || scope.Role != authpb.Role_ROLE_OWNER || res.User.Id.Type == userpb.UserType_USER_TYPE_FEDERATED { 111 gwRes := &gateway.AuthenticateResponse{ 112 Status: status.NewOK(ctx), 113 User: res.User, 114 Token: token, 115 } 116 return gwRes, nil 117 } 118 119 // we need to pass the token to authenticate the CreateHome request. 120 // TODO(labkode): appending to existing context will not pass the token. 121 ctx = ctxpkg.ContextSetToken(ctx, token) 122 ctx = ctxpkg.ContextSetUser(ctx, res.User) 123 ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, token) // TODO(jfd): hardcoded metadata key. use PerRPCCredentials? 124 125 // create home directory 126 createHomeRes, err := s.CreateHome(ctx, &storageprovider.CreateHomeRequest{}) 127 if err != nil { 128 log.Err(err).Msg("error calling CreateHome") 129 return &gateway.AuthenticateResponse{ 130 Status: status.NewInternal(ctx, "error creating user home"), 131 }, nil 132 } 133 134 if createHomeRes.Status.Code != rpc.Code_CODE_OK && createHomeRes.Status.Code != rpc.Code_CODE_ALREADY_EXISTS { 135 err := status.NewErrorFromCode(createHomeRes.Status.Code, "gateway") 136 log.Err(err).Msg("error calling Createhome") 137 return &gateway.AuthenticateResponse{ 138 Status: status.NewInternal(ctx, "error creating user home"), 139 }, nil 140 } 141 142 gwRes := &gateway.AuthenticateResponse{ 143 Status: status.NewOK(ctx), 144 User: res.User, 145 Token: token, 146 } 147 return gwRes, nil 148 } 149 150 func (s *svc) WhoAmI(ctx context.Context, req *gateway.WhoAmIRequest) (*gateway.WhoAmIResponse, error) { 151 u, _, err := s.tokenmgr.DismantleToken(ctx, req.Token) 152 if err != nil { 153 err = errors.Wrap(err, "gateway: error getting user from token") 154 return &gateway.WhoAmIResponse{ 155 Status: status.NewUnauthenticated(ctx, err, "error dismantling token"), 156 }, nil 157 } 158 159 if sharedconf.SkipUserGroupsInToken() { 160 groupsRes, err := s.GetUserGroups(ctx, &userpb.GetUserGroupsRequest{UserId: u.Id}) 161 if err != nil { 162 return nil, err 163 } 164 u.Groups = groupsRes.Groups 165 } 166 167 res := &gateway.WhoAmIResponse{ 168 Status: status.NewOK(ctx), 169 User: u, 170 } 171 return res, nil 172 } 173 174 func (s *svc) findAuthProvider(ctx context.Context, authType string) (authpb.ProviderAPIClient, error) { 175 c, err := pool.GetAuthRegistryServiceClient(s.c.AuthRegistryEndpoint) 176 if err != nil { 177 err = errors.Wrap(err, "gateway: error getting auth registry client") 178 return nil, err 179 } 180 181 res, err := c.GetAuthProviders(ctx, ®istry.GetAuthProvidersRequest{ 182 Type: authType, 183 }) 184 185 if err != nil { 186 err = errors.Wrap(err, "gateway: error calling GetAuthProvider") 187 return nil, err 188 } 189 190 if res.Status.Code == rpc.Code_CODE_OK && res.Providers != nil && len(res.Providers) > 0 { 191 // TODO(labkode): check for capabilities here 192 c, err := pool.GetAuthProviderServiceClient(res.Providers[0].Address) 193 if err != nil { 194 err = errors.Wrap(err, "gateway: error getting an auth provider client") 195 return nil, err 196 } 197 198 return c, nil 199 } 200 201 if res.Status.Code == rpc.Code_CODE_NOT_FOUND { 202 return nil, errtypes.NotFound("gateway: auth provider not found for type:" + authType) 203 } 204 205 return nil, errtypes.InternalError("gateway: error finding an auth provider for type: " + authType) 206 }