config.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package oauth
  2. import (
  3. "context"
  4. "crypto/rand"
  5. "encoding/base64"
  6. "time"
  7. "github.com/porter-dev/porter/internal/models/integrations"
  8. "github.com/porter-dev/porter/internal/repository"
  9. "golang.org/x/oauth2"
  10. )
  11. type Config struct {
  12. ClientID string
  13. ClientSecret string
  14. Scopes []string
  15. BaseURL string
  16. }
  17. // GithubAppConf is standard oauth2 config but it need to keeps track of the app name and webhook secret
  18. type GithubAppConf struct {
  19. AppName string
  20. WebhookSecret string
  21. oauth2.Config
  22. }
  23. func NewGithubClient(cfg *Config) *oauth2.Config {
  24. return &oauth2.Config{
  25. ClientID: cfg.ClientID,
  26. ClientSecret: cfg.ClientSecret,
  27. Endpoint: oauth2.Endpoint{
  28. AuthURL: "https://github.com/login/oauth/authorize",
  29. TokenURL: "https://github.com/login/oauth/access_token",
  30. },
  31. RedirectURL: cfg.BaseURL + "/api/oauth/github/callback",
  32. Scopes: cfg.Scopes,
  33. }
  34. }
  35. func NewGithubAppClient(cfg *Config, name string, secret string) *GithubAppConf {
  36. return &GithubAppConf{
  37. AppName: name,
  38. WebhookSecret: secret,
  39. Config: oauth2.Config{
  40. ClientID: cfg.ClientID,
  41. ClientSecret: cfg.ClientSecret,
  42. Endpoint: oauth2.Endpoint{
  43. AuthURL: "https://github.com/login/oauth/authorize",
  44. TokenURL: "https://github.com/login/oauth/access_token",
  45. },
  46. RedirectURL: cfg.BaseURL + "/api/oauth/github-app/callback",
  47. Scopes: cfg.Scopes,
  48. },
  49. }
  50. }
  51. func NewDigitalOceanClient(cfg *Config) *oauth2.Config {
  52. return &oauth2.Config{
  53. ClientID: cfg.ClientID,
  54. ClientSecret: cfg.ClientSecret,
  55. Endpoint: oauth2.Endpoint{
  56. AuthURL: "https://cloud.digitalocean.com/v1/oauth/authorize",
  57. TokenURL: "https://cloud.digitalocean.com/v1/oauth/token",
  58. },
  59. RedirectURL: cfg.BaseURL + "/api/oauth/digitalocean/callback",
  60. Scopes: cfg.Scopes,
  61. }
  62. }
  63. func NewGoogleClient(cfg *Config) *oauth2.Config {
  64. return &oauth2.Config{
  65. ClientID: cfg.ClientID,
  66. ClientSecret: cfg.ClientSecret,
  67. Endpoint: oauth2.Endpoint{
  68. AuthURL: "https://accounts.google.com/o/oauth2/v2/auth",
  69. TokenURL: "https://oauth2.googleapis.com/token",
  70. },
  71. RedirectURL: cfg.BaseURL + "/api/oauth/google/callback",
  72. Scopes: cfg.Scopes,
  73. }
  74. }
  75. func CreateRandomState() string {
  76. b := make([]byte, 16)
  77. rand.Read(b)
  78. state := base64.URLEncoding.EncodeToString(b)
  79. return state
  80. }
  81. // GetAccessToken retrieves an access token for a given client. It updates the
  82. // access token in the DB if necessary
  83. func GetAccessToken(
  84. o *integrations.OAuthIntegration,
  85. conf *oauth2.Config,
  86. repo repository.Repository,
  87. ) (string, *time.Time, error) {
  88. tokSource := conf.TokenSource(context.TODO(), &oauth2.Token{
  89. AccessToken: string(o.AccessToken),
  90. RefreshToken: string(o.RefreshToken),
  91. TokenType: "Bearer",
  92. })
  93. token, err := tokSource.Token()
  94. if err != nil {
  95. return "", nil, err
  96. }
  97. if token.AccessToken != string(o.AccessToken) {
  98. o.AccessToken = []byte(token.AccessToken)
  99. o.RefreshToken = []byte(token.RefreshToken)
  100. o, err = repo.OAuthIntegration.UpdateOAuthIntegration(o)
  101. if err != nil {
  102. return "", nil, err
  103. }
  104. }
  105. return token.AccessToken, &token.Expiry, nil
  106. }