Files
ipasso/backend/interface.go

72 lines
1.8 KiB
Go

package backend
import (
"context"
"crypto/rand"
"encoding/base64"
"errors"
"time"
)
type UserType string
var (
UtPerson UserType = "person"
UtHost UserType = "host"
UtService UserType = "service"
ErrTooManyAttempts error = errors.New("too many attempts")
ErrReservationSniped error = errors.New("session ID reservation expired and was sniped")
ErrBackendData error = errors.New("invalid data from backend")
)
// Session holds info about the logged-in user that won't change
type Session struct {
SessionID string
Expiration time.Time
UserID string
UserType UserType
LdapDN string
}
// SessionCache holds volatile information about the logged-in user
type SessionCache struct {
Valid bool
Groups []string
DisplayName string
GivenName string
FamilyName string
Email string
}
type Backend interface {
PutSession(ctx context.Context, session Session, cache SessionCache) error
GetSession(ctx context.Context, id string) (Session, *SessionCache, error)
EndSession(ctx context.Context, id string)
// ReserveSessionID attempts to reserve a session ID. If the ID was successfully reserved, return true
// A reserved session ID should time out no sooner than 60s from the reservation.
// Ergo, once reserved, a session ID should be used within 60s
ReserveSessionID(ctx context.Context, sessionID string) (bool, error)
DoMaintenance(ctx context.Context)
Ping(ctx context.Context) error
}
func NewSessionID(ctx context.Context, backend Backend) (string, error) {
var data = make([]byte, 18)
for i := 0; i < 10; i++ {
_, err := rand.Read(data[2:])
if err != nil {
return "", err
}
encoded := base64.URLEncoding.EncodeToString(data)
success, err := backend.ReserveSessionID(ctx, encoded)
if err != nil {
return "", err
}
if success {
return encoded, nil
}
}
return "", ErrTooManyAttempts
}