social.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package social
  2. import (
  3. "encoding/json"
  4. "strconv"
  5. "strings"
  6. "github.com/torkelo/grafana-pro/pkg/models"
  7. "github.com/torkelo/grafana-pro/pkg/setting"
  8. "golang.org/x/oauth2"
  9. )
  10. type BasicUserInfo struct {
  11. Identity string
  12. Name string
  13. Email string
  14. Login string
  15. Company string
  16. }
  17. type SocialConnector interface {
  18. Type() int
  19. UserInfo(token *oauth2.Token) (*BasicUserInfo, error)
  20. AuthCodeURL(state string, opts ...oauth2.AuthCodeOption) string
  21. Exchange(ctx oauth2.Context, code string) (*oauth2.Token, error)
  22. }
  23. var (
  24. SocialBaseUrl = "/login/"
  25. SocialMap = make(map[string]SocialConnector)
  26. )
  27. func NewOAuthService() {
  28. setting.OAuthService = &setting.OAuther{}
  29. setting.OAuthService.OAuthInfos = make(map[string]*setting.OAuthInfo)
  30. allOauthes := []string{"github", "google"}
  31. for _, name := range allOauthes {
  32. info := &setting.OAuthInfo{
  33. ClientId: setting.Cfg.MustValue("auth."+name, "client_id"),
  34. ClientSecret: setting.Cfg.MustValue("auth."+name, "client_secret"),
  35. Scopes: setting.Cfg.MustValueArray("auth."+name, "scopes", " "),
  36. AuthUrl: setting.Cfg.MustValue("auth."+name, "auth_url"),
  37. TokenUrl: setting.Cfg.MustValue("auth."+name, "token_url"),
  38. Enabled: setting.Cfg.MustBool("auth."+name, "enabled"),
  39. }
  40. if !info.Enabled {
  41. continue
  42. }
  43. setting.OAuthService.OAuthInfos[name] = info
  44. config := oauth2.Config{
  45. ClientID: info.ClientId,
  46. ClientSecret: info.ClientSecret,
  47. Endpoint: oauth2.Endpoint{
  48. AuthURL: info.AuthUrl,
  49. TokenURL: info.TokenUrl,
  50. },
  51. RedirectURL: strings.TrimSuffix(setting.AppUrl, "/") + SocialBaseUrl + name,
  52. Scopes: info.Scopes,
  53. }
  54. // GitHub.
  55. if name == "github" {
  56. setting.OAuthService.GitHub = true
  57. SocialMap["github"] = &SocialGithub{Config: &config}
  58. }
  59. // Google.
  60. if name == "google" {
  61. setting.OAuthService.Google = true
  62. SocialMap["google"] = &SocialGoogle{Config: &config}
  63. }
  64. }
  65. }
  66. type SocialGithub struct {
  67. *oauth2.Config
  68. }
  69. func (s *SocialGithub) Type() int {
  70. return int(models.GITHUB)
  71. }
  72. func (s *SocialGithub) UserInfo(token *oauth2.Token) (*BasicUserInfo, error) {
  73. var data struct {
  74. Id int `json:"id"`
  75. Name string `json:"login"`
  76. Email string `json:"email"`
  77. }
  78. var err error
  79. client := s.Client(oauth2.NoContext, token)
  80. r, err := client.Get("https://api.github.com/user")
  81. if err != nil {
  82. return nil, err
  83. }
  84. defer r.Body.Close()
  85. if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
  86. return nil, err
  87. }
  88. return &BasicUserInfo{
  89. Identity: strconv.Itoa(data.Id),
  90. Name: data.Name,
  91. Email: data.Email,
  92. }, nil
  93. }
  94. // ________ .__
  95. // / _____/ ____ ____ ____ | | ____
  96. // / \ ___ / _ \ / _ \ / ___\| | _/ __ \
  97. // \ \_\ ( <_> | <_> ) /_/ > |_\ ___/
  98. // \______ /\____/ \____/\___ /|____/\___ >
  99. // \/ /_____/ \/
  100. type SocialGoogle struct {
  101. *oauth2.Config
  102. }
  103. func (s *SocialGoogle) Type() int {
  104. return int(models.GOOGLE)
  105. }
  106. func (s *SocialGoogle) UserInfo(token *oauth2.Token) (*BasicUserInfo, error) {
  107. var data struct {
  108. Id string `json:"id"`
  109. Name string `json:"name"`
  110. Email string `json:"email"`
  111. }
  112. var err error
  113. reqUrl := "https://www.googleapis.com/oauth2/v1/userinfo"
  114. client := s.Client(oauth2.NoContext, token)
  115. r, err := client.Get(reqUrl)
  116. if err != nil {
  117. return nil, err
  118. }
  119. defer r.Body.Close()
  120. if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
  121. return nil, err
  122. }
  123. return &BasicUserInfo{
  124. Identity: data.Id,
  125. Name: data.Name,
  126. Email: data.Email,
  127. }, nil
  128. }