social.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package social
  2. import (
  3. "encoding/json"
  4. "strconv"
  5. "strings"
  6. "github.com/grafana/grafana/pkg/models"
  7. "github.com/grafana/grafana/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. sec := setting.Cfg.Section("auth." + name)
  33. info := &setting.OAuthInfo{
  34. ClientId: sec.Key("client_id").String(),
  35. ClientSecret: sec.Key("client_secret").String(),
  36. Scopes: sec.Key("scopes").Strings(" "),
  37. AuthUrl: sec.Key("auth_url").String(),
  38. TokenUrl: sec.Key("token_url").String(),
  39. Enabled: sec.Key("enabled").MustBool(),
  40. }
  41. if !info.Enabled {
  42. continue
  43. }
  44. setting.OAuthService.OAuthInfos[name] = info
  45. config := oauth2.Config{
  46. ClientID: info.ClientId,
  47. ClientSecret: info.ClientSecret,
  48. Endpoint: oauth2.Endpoint{
  49. AuthURL: info.AuthUrl,
  50. TokenURL: info.TokenUrl,
  51. },
  52. RedirectURL: strings.TrimSuffix(setting.AppUrl, "/") + SocialBaseUrl + name,
  53. Scopes: info.Scopes,
  54. }
  55. // GitHub.
  56. if name == "github" {
  57. setting.OAuthService.GitHub = true
  58. SocialMap["github"] = &SocialGithub{Config: &config}
  59. }
  60. // Google.
  61. if name == "google" {
  62. setting.OAuthService.Google = true
  63. SocialMap["google"] = &SocialGoogle{Config: &config}
  64. }
  65. }
  66. }
  67. type SocialGithub struct {
  68. *oauth2.Config
  69. }
  70. func (s *SocialGithub) Type() int {
  71. return int(models.GITHUB)
  72. }
  73. func (s *SocialGithub) UserInfo(token *oauth2.Token) (*BasicUserInfo, error) {
  74. var data struct {
  75. Id int `json:"id"`
  76. Name string `json:"login"`
  77. Email string `json:"email"`
  78. }
  79. var err error
  80. client := s.Client(oauth2.NoContext, token)
  81. r, err := client.Get("https://api.github.com/user")
  82. if err != nil {
  83. return nil, err
  84. }
  85. defer r.Body.Close()
  86. if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
  87. return nil, err
  88. }
  89. return &BasicUserInfo{
  90. Identity: strconv.Itoa(data.Id),
  91. Name: data.Name,
  92. Email: data.Email,
  93. }, nil
  94. }
  95. // ________ .__
  96. // / _____/ ____ ____ ____ | | ____
  97. // / \ ___ / _ \ / _ \ / ___\| | _/ __ \
  98. // \ \_\ ( <_> | <_> ) /_/ > |_\ ___/
  99. // \______ /\____/ \____/\___ /|____/\___ >
  100. // \/ /_____/ \/
  101. type SocialGoogle struct {
  102. *oauth2.Config
  103. }
  104. func (s *SocialGoogle) Type() int {
  105. return int(models.GOOGLE)
  106. }
  107. func (s *SocialGoogle) UserInfo(token *oauth2.Token) (*BasicUserInfo, error) {
  108. var data struct {
  109. Id string `json:"id"`
  110. Name string `json:"name"`
  111. Email string `json:"email"`
  112. }
  113. var err error
  114. reqUrl := "https://www.googleapis.com/oauth2/v1/userinfo"
  115. client := s.Client(oauth2.NoContext, token)
  116. r, err := client.Get(reqUrl)
  117. if err != nil {
  118. return nil, err
  119. }
  120. defer r.Body.Close()
  121. if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
  122. return nil, err
  123. }
  124. return &BasicUserInfo{
  125. Identity: data.Id,
  126. Name: data.Name,
  127. Email: data.Email,
  128. }, nil
  129. }