mirror of
https://github.com/netbirdio/dex.git
synced 2026-05-22 18:43:53 -07:00
6f2e233c7a
Signed-off-by: maksim.nabokikh <max.nabokih@gmail.com>
105 lines
2.3 KiB
Go
105 lines
2.3 KiB
Go
package session
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
|
|
"golang.org/x/oauth2"
|
|
)
|
|
|
|
// DeviceState holds the state of an active Device Code Flow.
|
|
type DeviceState struct {
|
|
DeviceCode string
|
|
UserCode string
|
|
VerificationURI string
|
|
PollInterval int
|
|
Token *oauth2.Token
|
|
}
|
|
|
|
// DeviceStore manages Device Code Flow sessions.
|
|
type DeviceStore interface {
|
|
// Save stores a new session and returns its ID.
|
|
// Previous sessions are considered invalidated.
|
|
Save(state DeviceState) string
|
|
|
|
// Get returns a session by ID. Returns false if the session
|
|
// is not found or has been invalidated by a newer one.
|
|
Get(sessionID string) (DeviceState, bool)
|
|
|
|
// GetLatest returns the most recent session and its ID.
|
|
// Returns false if no session exists.
|
|
GetLatest() (string, DeviceState, bool)
|
|
|
|
// SetToken attaches a token to the session.
|
|
// Returns false if the session is not found or not current.
|
|
SetToken(sessionID string, token *oauth2.Token) bool
|
|
}
|
|
|
|
// memoryDeviceStore is an in-memory DeviceStore that supports
|
|
// a single active session at a time.
|
|
type memoryDeviceStore struct {
|
|
mu sync.Mutex
|
|
sessionID string
|
|
state DeviceState
|
|
}
|
|
|
|
// NewMemoryDeviceStore creates an in-memory DeviceStore.
|
|
func NewMemoryDeviceStore() DeviceStore {
|
|
return &memoryDeviceStore{}
|
|
}
|
|
|
|
func (s *memoryDeviceStore) Save(state DeviceState) string {
|
|
id := generateSessionID()
|
|
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
s.sessionID = id
|
|
s.state = state
|
|
|
|
return id
|
|
}
|
|
|
|
func (s *memoryDeviceStore) Get(sessionID string) (DeviceState, bool) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
if sessionID != s.sessionID {
|
|
return DeviceState{}, false
|
|
}
|
|
return s.state, true
|
|
}
|
|
|
|
func (s *memoryDeviceStore) GetLatest() (string, DeviceState, bool) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
if s.sessionID == "" {
|
|
return "", DeviceState{}, false
|
|
}
|
|
return s.sessionID, s.state, true
|
|
}
|
|
|
|
func (s *memoryDeviceStore) SetToken(sessionID string, token *oauth2.Token) bool {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
if sessionID != s.sessionID {
|
|
return false
|
|
}
|
|
s.state.Token = token
|
|
return true
|
|
}
|
|
|
|
// generateSessionID creates a random session identifier.
|
|
func generateSessionID() string {
|
|
b := make([]byte, 16)
|
|
if _, err := rand.Read(b); err != nil {
|
|
return fmt.Sprintf("%d", time.Now().UnixNano())
|
|
}
|
|
return hex.EncodeToString(b)
|
|
}
|