package suites import ( "sync" "time" "github.com/authelia/otp/totp" "github.com/go-rod/rod/lib/proto" ) func NewRodSuiteCredentials() *RodSuiteCredentials { return &RodSuiteCredentials{ lock: &sync.Mutex{}, totp: map[string]RodSuiteCredentialOneTimePassword{}, } } type RodSuiteCredentials struct { lock *sync.Mutex totp map[string]RodSuiteCredentialOneTimePassword webauthn RodSuiteCredentialWebAuthn } type RodSuiteCredentialWebAuthn struct { AuthenticatorID proto.WebAuthnAuthenticatorID Credentials []*proto.WebAuthnCredential } func (rsc *RodSuiteCredentials) GetOneTimePassword(username string) RodSuiteCredentialOneTimePassword { rsc.lock.Lock() defer rsc.lock.Unlock() return rsc.totp[username] } func (rsc *RodSuiteCredentials) SetOneTimePassword(username string, credential RodSuiteCredentialOneTimePassword) { rsc.lock.Lock() defer rsc.lock.Unlock() credential.valid = true rsc.totp[username] = credential } func (rsc *RodSuiteCredentials) DeleteOneTimePassword(username string) { rsc.lock.Lock() defer rsc.lock.Unlock() rsc.totp[username] = RodSuiteCredentialOneTimePassword{ valid: false, } } func (rsc *RodSuiteCredentials) GetWebAuthnAuthenticatorID() (authenticatorID proto.WebAuthnAuthenticatorID) { rsc.lock.Lock() defer rsc.lock.Unlock() return rsc.webauthn.AuthenticatorID } func (rsc *RodSuiteCredentials) GetWebAuthnCredentials() (credentials []*proto.WebAuthnCredential) { rsc.lock.Lock() defer rsc.lock.Unlock() return rsc.webauthn.Credentials } func (rsc *RodSuiteCredentials) GetWebAuthnAuthenticator() (authenticatorID proto.WebAuthnAuthenticatorID, credentials []*proto.WebAuthnCredential) { rsc.lock.Lock() defer rsc.lock.Unlock() return rsc.webauthn.AuthenticatorID, rsc.webauthn.Credentials } func (rsc *RodSuiteCredentials) SetWebAuthnAuthenticatorID(authenticatorID proto.WebAuthnAuthenticatorID) { rsc.lock.Lock() defer rsc.lock.Unlock() rsc.webauthn.AuthenticatorID = authenticatorID } func (rsc *RodSuiteCredentials) SetWebAuthnAuthenticatorCredentials(credentials ...*proto.WebAuthnCredential) { rsc.lock.Lock() defer rsc.lock.Unlock() rsc.webauthn.Credentials = nil for _, credential := range credentials { if credential.RpID == "" { continue } rsc.webauthn.Credentials = append(rsc.webauthn.Credentials, credential) } } func (rsc *RodSuiteCredentials) DeleteWebAuthnAuthenticatorCredentials() { rsc.lock.Lock() defer rsc.lock.Unlock() rsc.webauthn.Credentials = nil } func (rsc *RodSuiteCredentials) UpdateWebAuthnAuthenticator(funcUpdate func(authenticatorID proto.WebAuthnAuthenticatorID, credentials []*proto.WebAuthnCredential) (proto.WebAuthnAuthenticatorID, []*proto.WebAuthnCredential)) { if funcUpdate == nil { return } rsc.lock.Lock() defer rsc.lock.Unlock() credentials := make([]*proto.WebAuthnCredential, len(rsc.webauthn.Credentials)) if len(credentials) != 0 { copy(credentials, rsc.webauthn.Credentials) } rsc.webauthn.AuthenticatorID, rsc.webauthn.Credentials = funcUpdate(rsc.webauthn.AuthenticatorID, credentials) } func (rsc *RodSuiteCredentials) DeleteWebAuthnAuthenticator() { rsc.lock.Lock() defer rsc.lock.Unlock() rsc.webauthn = RodSuiteCredentialWebAuthn{} } type RodSuiteCredentialsProvider interface { GetOneTimePassword(username string) RodSuiteCredentialOneTimePassword SetOneTimePassword(username string, credential RodSuiteCredentialOneTimePassword) DeleteOneTimePassword(username string) GetWebAuthnAuthenticatorID() (authenticatorID proto.WebAuthnAuthenticatorID) GetWebAuthnCredentials() (credentials []*proto.WebAuthnCredential) SetWebAuthnAuthenticatorID(authenticatorID proto.WebAuthnAuthenticatorID) SetWebAuthnAuthenticatorCredentials(credentials ...*proto.WebAuthnCredential) DeleteWebAuthnAuthenticatorCredentials() GetWebAuthnAuthenticator() (authenticatorID proto.WebAuthnAuthenticatorID, credentials []*proto.WebAuthnCredential) UpdateWebAuthnAuthenticator(funcUpdate func(authenticatorID proto.WebAuthnAuthenticatorID, credentials []*proto.WebAuthnCredential) (proto.WebAuthnAuthenticatorID, []*proto.WebAuthnCredential)) DeleteWebAuthnAuthenticator() } type RodSuiteCredentialOneTimePassword struct { valid bool Secret string ValidationOptions totp.ValidateOpts } func (otp *RodSuiteCredentialOneTimePassword) Valid() bool { return otp.valid } func (otp *RodSuiteCredentialOneTimePassword) Generate(at time.Time) (passcode string, err error) { return totp.GenerateCodeCustom(otp.Secret, at, otp.ValidationOptions) }