Session: set authID and authenticatedBy (#85806)

* Authn: Resolve authenticate by and auth id when fethcing signed in user

* Change logout client interface to only take Requester interface

* Session: Fetch external auth info when authenticating sessions

* Use authenticated by from identity

* Move call to get auth-info into session client and use GetAuthenticatedBy in various places
This commit is contained in:
Karl Persson
2024-04-11 10:25:29 +02:00
committed by GitHub
parent f375af793f
commit 895222725c
21 changed files with 230 additions and 185 deletions
+11 -43
View File
@@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"strconv"
"time"
"github.com/go-jose/go-jose/v3/jwt"
@@ -17,8 +16,6 @@ import (
"github.com/grafana/grafana/pkg/services/auth/identity"
"github.com/grafana/grafana/pkg/services/authn"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
@@ -33,12 +30,12 @@ var _ auth.IDService = (*Service)(nil)
func ProvideService(
cfg *setting.Cfg, signer auth.IDSigner, cache remotecache.CacheStorage,
features featuremgmt.FeatureToggles, authnService authn.Service,
authInfoService login.AuthInfoService, reg prometheus.Registerer,
reg prometheus.Registerer,
) *Service {
s := &Service{
cfg: cfg, logger: log.New("id-service"),
signer: signer, cache: cache,
authInfoService: authInfoService, metrics: newMetrics(reg),
metrics: newMetrics(reg),
}
if features.IsEnabledGlobally(featuremgmt.FlagIdForwarding) {
@@ -49,13 +46,12 @@ func ProvideService(
}
type Service struct {
cfg *setting.Cfg
logger log.Logger
signer auth.IDSigner
cache remotecache.CacheStorage
authInfoService login.AuthInfoService
si singleflight.Group
metrics *metrics
cfg *setting.Cfg
logger log.Logger
signer auth.IDSigner
cache remotecache.CacheStorage
si singleflight.Group
metrics *metrics
}
func (s *Service) SignIdentity(ctx context.Context, id identity.Requester) (string, error) {
@@ -90,9 +86,9 @@ func (s *Service) SignIdentity(ctx context.Context, id identity.Requester) (stri
}
if identity.IsNamespace(namespace, identity.NamespaceUser) {
if err := s.setUserClaims(ctx, id, identifier, claims); err != nil {
return "", err
}
claims.Email = id.GetEmail()
claims.EmailVerified = id.IsEmailVerified()
claims.AuthenticatedBy = id.GetAuthenticatedBy()
}
token, err := s.signer.SignIDToken(ctx, claims)
@@ -134,34 +130,6 @@ func (s *Service) RemoveIDToken(ctx context.Context, id identity.Requester) erro
return s.cache.Delete(ctx, prefixCacheKey(id.GetCacheKey()))
}
func (s *Service) setUserClaims(ctx context.Context, ident identity.Requester, identifier string, claims *auth.IDClaims) error {
id, err := strconv.ParseInt(identifier, 10, 64)
if err != nil {
return err
}
if id == 0 {
return nil
}
claims.Email = ident.GetEmail()
claims.EmailVerified = ident.IsEmailVerified()
info, err := s.authInfoService.GetAuthInfo(ctx, &login.GetAuthInfoQuery{UserId: id})
if err != nil {
// we ignore errors when a user don't have external user auth
if !errors.Is(err, user.ErrUserNotFound) {
s.logger.FromContext(ctx).Error("Failed to fetch auth info", "userId", id, "error", err)
}
return nil
}
claims.AuthenticatedBy = info.AuthModule
return nil
}
func (s *Service) hook(ctx context.Context, identity *authn.Identity, _ *authn.Request) error {
// FIXME(kalleep): we should probably lazy load this
token, err := s.SignIdentity(ctx, identity)
+5 -7
View File
@@ -16,8 +16,6 @@ import (
"github.com/grafana/grafana/pkg/services/authn/authntest"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/login/authinfotest"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
@@ -32,7 +30,7 @@ func Test_ProvideService(t *testing.T) {
},
}
_ = ProvideService(setting.NewCfg(), nil, nil, features, authnService, nil, nil)
_ = ProvideService(setting.NewCfg(), nil, nil, features, authnService, nil)
assert.True(t, hookRegistered)
})
@@ -46,7 +44,7 @@ func Test_ProvideService(t *testing.T) {
},
}
_ = ProvideService(setting.NewCfg(), nil, nil, features, authnService, nil, nil)
_ = ProvideService(setting.NewCfg(), nil, nil, features, authnService, nil)
assert.False(t, hookRegistered)
})
}
@@ -69,7 +67,7 @@ func TestService_SignIdentity(t *testing.T) {
s := ProvideService(
setting.NewCfg(), signer, remotecache.NewFakeCacheStorage(),
featuremgmt.WithFeatures(featuremgmt.FlagIdForwarding),
&authntest.FakeService{}, &authinfotest.FakeService{ExpectedError: user.ErrUserNotFound}, nil,
&authntest.FakeService{}, nil,
)
token, err := s.SignIdentity(context.Background(), &authn.Identity{ID: "user:1"})
require.NoError(t, err)
@@ -80,9 +78,9 @@ func TestService_SignIdentity(t *testing.T) {
s := ProvideService(
setting.NewCfg(), signer, remotecache.NewFakeCacheStorage(),
featuremgmt.WithFeatures(featuremgmt.FlagIdForwarding),
&authntest.FakeService{}, &authinfotest.FakeService{ExpectedUserAuth: &login.UserAuth{AuthModule: login.AzureADAuthModule}}, nil,
&authntest.FakeService{}, nil,
)
token, err := s.SignIdentity(context.Background(), &authn.Identity{ID: "user:1"})
token, err := s.SignIdentity(context.Background(), &authn.Identity{ID: "user:1", AuthenticatedBy: login.AzureADAuthModule})
require.NoError(t, err)
parsed, err := jwt.ParseSigned(token)