Authn: Add function to resolve identity from org and namespace id (#84555)

* Add function to get the namespaced id

* Add function to resolve an identity through authn.Service from org and namespace id

* Switch to resolve identity for re-authenticate in another org
This commit is contained in:
Karl Persson
2024-03-15 15:08:15 +01:00
committed by GitHub
parent ced09883d3
commit d4e802dd47
9 changed files with 101 additions and 30 deletions
+4
View File
@@ -77,6 +77,10 @@ type Service interface {
RedirectURL(ctx context.Context, client string, r *Request) (*Redirect, error)
// Logout revokes session token and does additional clean up if client used to authenticate supports it
Logout(ctx context.Context, user identity.Requester, sessionToken *usertoken.UserToken) (*Redirect, error)
// ResolveIdentity resolves an identity from org and namespace id.
ResolveIdentity(ctx context.Context, orgID int64, namespaceID string) (*Identity, error)
// RegisterClient will register a new authn.Client that can be used for authentication
RegisterClient(c Client)
}
+14
View File
@@ -391,6 +391,20 @@ Default:
return redirect, nil
}
func (s *Service) ResolveIdentity(ctx context.Context, orgID int64, namespaceID string) (*authn.Identity, error) {
r := &authn.Request{}
r.OrgID = orgID
// hack to not update last seen
r.SetMeta(authn.MetaKeyIsLogin, "true")
identity, err := s.authenticate(ctx, clients.ProvideIdentity(namespaceID), r)
if err != nil {
return nil, err
}
return identity, nil
}
func (s *Service) RegisterClient(c authn.Client) {
s.clients[c.Name()] = c
if cac, ok := c.(authn.ContextAwareClient); ok {
+5 -1
View File
@@ -68,7 +68,11 @@ func (f *FakeService) RedirectURL(ctx context.Context, client string, r *authn.R
return f.ExpectedRedirect, f.ExpectedErr
}
func (*FakeService) Logout(_ context.Context, _ identity.Requester, _ *usertoken.UserToken) (*authn.Redirect, error) {
func (f *FakeService) Logout(_ context.Context, _ identity.Requester, _ *usertoken.UserToken) (*authn.Redirect, error) {
panic("unimplemented")
}
func (f *FakeService) ResolveIdentity(ctx context.Context, orgID int64, namespaceID string) (*authn.Identity, error) {
panic("unimplemented")
}
+4
View File
@@ -47,6 +47,10 @@ func (*MockService) Logout(_ context.Context, _ identity.Requester, _ *usertoken
panic("unimplemented")
}
func (m *MockService) ResolveIdentity(ctx context.Context, orgID int64, namespaceID string) (*authn.Identity, error) {
panic("unimplemented")
}
func (m *MockService) SyncIdentity(ctx context.Context, identity *authn.Identity) error {
if m.SyncIdentityFunc != nil {
return m.SyncIdentityFunc(ctx, identity)
+33
View File
@@ -0,0 +1,33 @@
package clients
import (
"context"
"github.com/grafana/grafana/pkg/services/authn"
)
var _ authn.Client = (*IdentityClient)(nil)
func ProvideIdentity(namespaceID string) *IdentityClient {
return &IdentityClient{namespaceID}
}
type IdentityClient struct {
namespaceID string
}
func (i *IdentityClient) Name() string {
return "identity"
}
// Authenticate implements authn.Client.
func (i *IdentityClient) Authenticate(ctx context.Context, r *authn.Request) (*authn.Identity, error) {
return &authn.Identity{
OrgID: r.OrgID,
ID: i.namespaceID,
ClientParams: authn.ClientParams{
FetchSyncedUser: true,
SyncPermissions: true,
},
}, nil
}
+12 -10
View File
@@ -87,6 +87,18 @@ type Identity struct {
IDToken string
}
func (i *Identity) GetID() string {
return i.ID
}
func (i *Identity) GetNamespacedID() (namespace string, identifier string) {
split := strings.Split(i.GetID(), ":")
if len(split) != 2 {
return "", ""
}
return split[0], split[1]
}
func (i *Identity) GetAuthenticatedBy() string {
return i.AuthenticatedBy
}
@@ -122,16 +134,6 @@ func (i *Identity) GetLogin() string {
return i.Login
}
func (i *Identity) GetNamespacedID() (namespace string, identifier string) {
split := strings.Split(i.ID, ":")
if len(split) != 2 {
return "", ""
}
return split[0], split[1]
}
// GetOrgID implements identity.Requester.
func (i *Identity) GetOrgID() int64 {
return i.OrgID