package credentials import "time" type AuthType string const ( AuthPassword AuthType = "password" AuthOAuth2 AuthType = "oauth2" ) // Credential is the decrypted mail account secret material. type Credential struct { AuthType AuthType Username string Password string AccessToken string RefreshToken string Expiry time.Time OAuthProvider string // google | microsoft } func (c Credential) IsOAuth() bool { return c.AuthType == AuthOAuth2 } func (c Credential) NeedsRefresh() bool { if !c.IsOAuth() || c.RefreshToken == "" { return false } if c.Expiry.IsZero() { return false } return time.Now().Add(2 * time.Minute).After(c.Expiry) } type storedPayload struct { AuthType string `json:"auth_type,omitempty"` Username string `json:"username"` Password string `json:"password,omitempty"` AccessToken string `json:"access_token,omitempty"` RefreshToken string `json:"refresh_token,omitempty"` Expiry string `json:"expiry,omitempty"` OAuthProvider string `json:"oauth_provider,omitempty"` } func (c Credential) toStored() storedPayload { p := storedPayload{ AuthType: string(c.AuthType), Username: c.Username, Password: c.Password, AccessToken: c.AccessToken, RefreshToken: c.RefreshToken, OAuthProvider: c.OAuthProvider, } if !c.Expiry.IsZero() { p.Expiry = c.Expiry.UTC().Format(time.RFC3339) } if p.AuthType == "" { p.AuthType = string(AuthPassword) } return p } func storedToCredential(p storedPayload) (Credential, error) { authType := AuthType(p.AuthType) if authType == "" { authType = AuthPassword } c := Credential{ AuthType: authType, Username: p.Username, Password: p.Password, AccessToken: p.AccessToken, RefreshToken: p.RefreshToken, OAuthProvider: p.OAuthProvider, } if p.Expiry != "" { t, err := time.Parse(time.RFC3339, p.Expiry) if err != nil { return Credential{}, err } c.Expiry = t } if c.Username == "" { return Credential{}, errIncomplete } switch authType { case AuthPassword: if c.Password == "" { return Credential{}, errIncomplete } case AuthOAuth2: if c.AccessToken == "" { return Credential{}, errIncomplete } default: return Credential{}, errUnsupportedAuth } return c, nil }