Skip to content

Commit

Permalink
feat: add login manager (#1506)
Browse files Browse the repository at this point in the history
* feat: add login manager

* chore: login manager files

* chore: register login manager

* chore: fix tests

Some api layer tests require a real authenticator, so the jimm suite has been modified to support this.
Also fixes some unit tests that needed to update how they setup their mocks.

* chore: fixes after rebase

Fix DB migration signature

* chore: fix package docstrings

added nil oauth interface check and some docstrings
  • Loading branch information
kian99 authored Jan 7, 2025
1 parent a314019 commit 31d642f
Show file tree
Hide file tree
Showing 25 changed files with 632 additions and 465 deletions.
2 changes: 1 addition & 1 deletion cmd/jimmsrv/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ func NewService(ctx context.Context, p Params) (*Service, error) {
return nil, errors.E(op, err)
}

s.mux.Mount("/rebac", middleware.AuthenticateRebac("/rebac", rebacBackend.Handler(""), s.jimm))
s.mux.Mount("/rebac", middleware.AuthenticateRebac("/rebac", rebacBackend.Handler(""), s.jimm.LoginManager()))

mountHandler(
"/debug",
Expand Down
104 changes: 0 additions & 104 deletions internal/jimm/admin.go

This file was deleted.

108 changes: 0 additions & 108 deletions internal/jimm/admin_test.go

This file was deleted.

8 changes: 0 additions & 8 deletions internal/jimm/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,6 @@ func (j *JIMM) ParseAndValidateTag(ctx context.Context, key string) (*ofganames.
return j.parseAndValidateTag(ctx, key)
}

func (j *JIMM) GetUser(ctx context.Context, identifier string) (*openfga.User, error) {
return j.getUser(ctx, identifier)
}

func (j *JIMM) UpdateUserLastLogin(ctx context.Context, identifier string) error {
return j.updateUserLastLogin(ctx, identifier)
}

func (j *JIMM) EveryoneUser() *openfga.User {
return j.everyoneUser()
}
34 changes: 34 additions & 0 deletions internal/jimm/jimm.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/canonical/jimm/v3/internal/jimm/credentials"
"github.com/canonical/jimm/v3/internal/jimm/group"
"github.com/canonical/jimm/v3/internal/jimm/identity"
"github.com/canonical/jimm/v3/internal/jimm/login"
"github.com/canonical/jimm/v3/internal/jimm/role"
"github.com/canonical/jimm/v3/internal/jimmjwx"
"github.com/canonical/jimm/v3/internal/openfga"
Expand Down Expand Up @@ -149,6 +150,24 @@ type IdentityManager interface {
CountIdentities(ctx context.Context, user *openfga.User) (int, error)
}

// LoginManager provides methods for login/authentication and creates identities (users).
type LoginManager interface {
// AuthenticateBrowserSession authenticates a browser login.
AuthenticateBrowserSession(ctx context.Context, w http.ResponseWriter, req *http.Request) (context.Context, error)
// LoginDevice starts the device login flow.
LoginDevice(ctx context.Context) (*oauth2.DeviceAuthResponse, error)
// GetDeviceSessionToken returns a session token scoped to the user's identity.
GetDeviceSessionToken(ctx context.Context, deviceOAuthResponse *oauth2.DeviceAuthResponse) (string, error)
// LoginClientCredentials logs in a user with client credentials.
LoginClientCredentials(ctx context.Context, clientID string, clientSecret string) (*openfga.User, error)
// LoginWithSessionToken logs in a user with a session token.
LoginWithSessionToken(ctx context.Context, sessionToken string) (*openfga.User, error)
// LoginWithSessionCookie logs in a user assuming cookie auth was done previously.
LoginWithSessionCookie(ctx context.Context, identityID string) (*openfga.User, error)
// UserLogin creates/fetches an identity based on the identity provided and returns an openfga user object.
UserLogin(ctx context.Context, identity string) (*openfga.User, error)
}

// Parameters holds the services and static fields passed to the jimm.New() constructor.
// You can provide mock implementations of certain services where necessary for dependency injection.
type Parameters struct {
Expand Down Expand Up @@ -262,6 +281,12 @@ func New(p Parameters) (*JIMM, error) {
}
j.identityManager = identityManager

loginManager, err := login.NewLoginManager(j.Database, j.OpenFGAClient, j.OAuthAuthenticator, j.ResourceTag())
if err != nil {
return nil, err
}
j.loginManager = loginManager

return j, nil
}

Expand All @@ -278,7 +303,11 @@ type JIMM struct {
// groupManager provides a means to manage groups within JIMM.
groupManager GroupManager

// identityManager provides a means to manage identities within JIMM.
identityManager IdentityManager

// loginManager provides a means to authenticate and login/create users/identities within JIMM.
loginManager LoginManager
}

// ResourceTag returns JIMM's controller tag stating its UUID.
Expand Down Expand Up @@ -306,6 +335,11 @@ func (j *JIMM) IdentityManager() IdentityManager {
return j.identityManager
}

// Login manager returns a manager that enables login and authentication.
func (j *JIMM) LoginManager() LoginManager {
return j.loginManager
}

type permission struct {
resource string
relation string
Expand Down
16 changes: 16 additions & 0 deletions internal/jimm/login/export_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2025 Canonical.

package login

import (
"context"

"github.com/canonical/jimm/v3/internal/openfga"
)

// Login is a type alias to export loginManager for use in tests.
type LoginManager = loginManager

func (j *LoginManager) GetOrCreateIdentity(ctx context.Context, identifier string) (*openfga.User, error) {
return j.getOrCreateIdentity(ctx, identifier)
}
Loading

0 comments on commit 31d642f

Please sign in to comment.