main.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io"
  6. "log"
  7. "net/http"
  8. "os"
  9. "path/filepath"
  10. "time"
  11. )
  12. type userMapping struct {
  13. SFTPGoUsername string
  14. AuthyID int64
  15. AuthyAPIKey string
  16. }
  17. // we assume that the SFTPGo already exists, we only check the one time token.
  18. // If you need to create the SFTPGo user more fields are needed here
  19. type minimalSFTPGoUser struct {
  20. Status int `json:"status,omitempty"`
  21. Username string `json:"username"`
  22. HomeDir string `json:"home_dir,omitempty"`
  23. Permissions map[string][]string `json:"permissions"`
  24. }
  25. var (
  26. mapping []userMapping
  27. )
  28. func init() {
  29. // this is for demo only, you probably want to get this mapping dynamically, for example using a database query
  30. mapping = append(mapping, userMapping{
  31. SFTPGoUsername: "<SFTPGo username>",
  32. AuthyID: 1234567,
  33. AuthyAPIKey: "<your api key>",
  34. })
  35. }
  36. func printResponse(username string) {
  37. u := minimalSFTPGoUser{
  38. Username: username,
  39. Status: 1,
  40. HomeDir: filepath.Join(os.TempDir(), username),
  41. }
  42. u.Permissions = make(map[string][]string)
  43. u.Permissions["/"] = []string{"*"}
  44. resp, _ := json.Marshal(u)
  45. fmt.Printf("%v\n", string(resp))
  46. if len(username) > 0 {
  47. os.Exit(0)
  48. } else {
  49. os.Exit(1)
  50. }
  51. }
  52. func main() {
  53. // get credentials from env vars
  54. username := os.Getenv("SFTPGO_AUTHD_USERNAME")
  55. password := os.Getenv("SFTPGO_AUTHD_PASSWORD")
  56. if len(password) == 0 {
  57. // login method is not password
  58. printResponse("")
  59. return
  60. }
  61. for _, m := range mapping {
  62. if m.SFTPGoUsername == username {
  63. // mapping found we can now verify the token
  64. url := fmt.Sprintf("https://api.authy.com/protected/json/verify/%v/%v", password, m.AuthyID)
  65. req, err := http.NewRequest(http.MethodGet, url, nil)
  66. if err != nil {
  67. log.Fatal(err)
  68. }
  69. req.Header.Set("X-Authy-API-Key", m.AuthyAPIKey)
  70. httpClient := &http.Client{
  71. Timeout: 10 * time.Second,
  72. }
  73. resp, err := httpClient.Do(req)
  74. if err != nil {
  75. printResponse("")
  76. }
  77. defer resp.Body.Close()
  78. if resp.StatusCode != http.StatusOK {
  79. // status code 200 is expected
  80. printResponse("")
  81. }
  82. var authyResponse map[string]interface{}
  83. respBody, err := io.ReadAll(resp.Body)
  84. if err != nil {
  85. printResponse("")
  86. }
  87. err = json.Unmarshal(respBody, &authyResponse)
  88. if err != nil {
  89. printResponse("")
  90. }
  91. if authyResponse["success"].(string) == "true" {
  92. printResponse(username)
  93. }
  94. printResponse("")
  95. break
  96. }
  97. }
  98. // no mapping found
  99. printResponse("")
  100. }