2024-10-11 16:47:52 -04:00
|
|
|
package ctx
|
|
|
|
|
|
|
|
|
|
import (
|
2024-10-12 12:52:20 -04:00
|
|
|
"errors"
|
2024-10-11 16:47:52 -04:00
|
|
|
"fmt"
|
|
|
|
|
|
|
|
|
|
"github.com/go-webauthn/webauthn/protocol"
|
|
|
|
|
"github.com/labstack/echo/v4"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type WebBytes = protocol.URLEncodedBase64
|
|
|
|
|
|
2024-10-12 12:52:20 -04:00
|
|
|
type Session struct {
|
2024-10-11 16:47:52 -04:00
|
|
|
// Defaults
|
2024-10-12 12:52:20 -04:00
|
|
|
ID string // Generated ksuid http cookie; Initialized on first request
|
|
|
|
|
Origin string // Webauthn mapping to Relaying Party ID; Initialized on first request
|
|
|
|
|
UserAgent string
|
|
|
|
|
Platform string
|
2024-10-11 16:47:52 -04:00
|
|
|
|
|
|
|
|
// Initialization
|
2024-10-12 12:52:20 -04:00
|
|
|
Address string // Webauthn mapping to User ID; Supplied by DWN frontend
|
|
|
|
|
ChainID string // Macaroon mapping to location; Supplied by DWN frontend
|
|
|
|
|
|
|
|
|
|
Subject string // Webauthn mapping to User Displayable Name; Supplied by DWN frontend
|
2024-10-11 16:47:52 -04:00
|
|
|
|
|
|
|
|
// Authentication
|
|
|
|
|
challenge WebBytes // Webauthn mapping to Challenge; Per session based on origin
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-12 12:52:20 -04:00
|
|
|
func (s *Session) GetChallenge(subject string) (WebBytes, error) {
|
|
|
|
|
// Check if challenge is already set and subject matches
|
|
|
|
|
if s.Subject != "" && s.Subject != subject {
|
|
|
|
|
return nil, errors.New("challenge already set, and subject does not match")
|
|
|
|
|
} else if s.Subject == "" {
|
|
|
|
|
s.Subject = subject
|
|
|
|
|
} else {
|
|
|
|
|
return s.challenge, nil
|
|
|
|
|
}
|
2024-10-11 16:47:52 -04:00
|
|
|
|
|
|
|
|
if s.challenge == nil {
|
2024-10-12 12:52:20 -04:00
|
|
|
chl, err := protocol.CreateChallenge()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
s.challenge = chl
|
2024-10-11 16:47:52 -04:00
|
|
|
}
|
|
|
|
|
return s.challenge, nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-12 12:52:20 -04:00
|
|
|
func (s *Session) ValidateChallenge(challenge WebBytes, subject string) error {
|
2024-10-11 16:47:52 -04:00
|
|
|
if s.challenge == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
if s.challenge.String() != challenge.String() {
|
|
|
|
|
return fmt.Errorf("invalid challenge")
|
|
|
|
|
}
|
2024-10-12 12:52:20 -04:00
|
|
|
s.Subject = subject
|
2024-10-11 16:47:52 -04:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-12 12:52:20 -04:00
|
|
|
func GetSession(c echo.Context) *Session {
|
|
|
|
|
id, _ := getSessionID(c.Request().Context())
|
|
|
|
|
return buildSession(c, id)
|
2024-10-11 16:47:52 -04:00
|
|
|
}
|
|
|
|
|
|
2024-10-12 12:52:20 -04:00
|
|
|
func SetAddress(c echo.Context, address string) *Session {
|
|
|
|
|
// Write address to X-Sonr-Address header
|
|
|
|
|
c.Response().Header().Set("X-Sonr-Address", address)
|
|
|
|
|
return buildSession(c, "")
|
2024-10-11 16:47:52 -04:00
|
|
|
}
|