Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add peer login expiration #682

Merged
merged 8 commits into from
Feb 13, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions management/server/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ type AccountManager interface {
GetDNSSettings(accountID string, userID string) (*DNSSettings, error)
SaveDNSSettings(accountID string, userID string, dnsSettingsToSave *DNSSettings) error
GetPeer(accountID, peerID, userID string) (*Peer, error)
UpdatePeerLastLogin(peerID string) error
}

type DefaultAccountManager struct {
Expand Down
52 changes: 37 additions & 15 deletions management/server/grpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,29 +201,37 @@ func (s *GRPCServer) Sync(req *proto.EncryptedMessage, srv proto.ManagementServi
}
}

func (s *GRPCServer) validateToken(jwtToken string) (string, error) {
if s.jwtMiddleware == nil {
return "", status.Error(codes.Internal, "no jwt middleware set")
}

token, err := s.jwtMiddleware.ValidateAndParse(jwtToken)
if err != nil {
return "", status.Errorf(codes.Internal, "invalid jwt token, err: %v", err)
}
claims := s.jwtClaimsExtractor.FromToken(token)
// we need to call this method because if user is new, we will automatically add it to existing or create a new account
_, _, err = s.accountManager.GetAccountFromToken(claims)
if err != nil {
return "", status.Errorf(codes.Internal, "unable to fetch account with claims, err: %v", err)
}

return claims.UserId, nil
}

func (s *GRPCServer) registerPeer(peerKey wgtypes.Key, req *proto.LoginRequest) (*Peer, error) {
var (
reqSetupKey string
userID string
err error
)

if req.GetJwtToken() != "" {
log.Debugln("using jwt token to register peer")

if s.jwtMiddleware == nil {
return nil, status.Error(codes.Internal, "no jwt middleware set")
}

token, err := s.jwtMiddleware.ValidateAndParse(req.GetJwtToken())
userID, err = s.validateToken(req.JwtToken)
if err != nil {
return nil, status.Errorf(codes.Internal, "invalid jwt token, err: %v", err)
}
claims := s.jwtClaimsExtractor.FromToken(token)
userID = claims.UserId
// we need to call this method because if user is new, we will automatically add it to existing or create a new account
_, _, err = s.accountManager.GetAccountFromToken(claims)
if err != nil {
return nil, status.Errorf(codes.Internal, "unable to fetch account with claims, err: %v", err)
return nil, err
}
} else {
log.Debugln("using setup key to register peer")
Expand Down Expand Up @@ -359,9 +367,23 @@ func (s *GRPCServer) Login(ctx context.Context, req *proto.EncryptedMessage) (*p
}
}

// check if peer login has expired
braginini marked this conversation as resolved.
Show resolved Hide resolved
expired, left := peer.LoginExpired(24 * time.Hour)
if peer.UserID != "" && expired {
return nil, status.Errorf(codes.PermissionDenied, "peer login has expired %v ago. Please log in once more", left)
// it might be that peer expired but user has logged in already, check token then
if loginReq.GetJwtToken() == "" {
return nil, status.Errorf(codes.PermissionDenied,
"peer login has expired %v ago. Please log in once more", left)
}
_, err = s.validateToken(loginReq.GetJwtToken())
if err != nil {
return nil, err
}

err = s.accountManager.UpdatePeerLastLogin(peer.ID)
if err != nil {
return nil, err
}
}

var sshKey []byte
Expand Down
31 changes: 31 additions & 0 deletions management/server/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,37 @@ func (am *DefaultAccountManager) AddPeer(setupKey, userID string, peer *Peer) (*
return newPeer, nil
}

func (am *DefaultAccountManager) UpdatePeerLastLogin(peerID string) error {
account, err := am.Store.GetAccountByPeerID(peerID)
if err != nil {
return err
}

unlock := am.Store.AcquireAccountLock(account.Id)
defer unlock()

// ensure that we consider modification happened meanwhile (because we were outside the account lock when we fetched the account)
account, err = am.Store.GetAccount(account.Id)
if err != nil {
return err
}

peer := account.GetPeer(peerID)
if peer == nil {
return status.Errorf(status.NotFound, "peer with ID %s not found", peerID)
}

peer.LastLogin = time.Now()
account.UpdatePeer(peer)

err = am.Store.SaveAccount(account)
if err != nil {
return err
}

return nil
}

// UpdatePeerSSHKey updates peer's public SSH key
func (am *DefaultAccountManager) UpdatePeerSSHKey(peerID string, sshKey string) error {

Expand Down