api_oauth_github.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package api
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. log "github.com/alecthomas/log4go"
  6. "github.com/gin-gonic/gin"
  7. "github.com/golang/oauth2"
  8. "github.com/torkelo/grafana-pro/pkg/models"
  9. "github.com/torkelo/grafana-pro/pkg/stores"
  10. )
  11. var (
  12. githubOAuthConfig *oauth2.Config
  13. githubRedirectUrl string = "http://localhost:3000/oauth2/github/callback"
  14. githubAuthUrl string = "https://github.com/login/oauth/authorize"
  15. githubTokenUrl string = "https://github.com/login/oauth/access_token"
  16. )
  17. func init() {
  18. addRoutes(func(self *HttpServer) {
  19. if !self.cfg.Http.GithubOAuth.Enabled {
  20. return
  21. }
  22. self.router.GET("/oauth2/github", self.oauthGithub)
  23. self.router.GET("/oauth2/github/callback", self.oauthGithubCallback)
  24. options := &oauth2.Options{
  25. ClientID: self.cfg.Http.GithubOAuth.ClientId,
  26. ClientSecret: self.cfg.Http.GithubOAuth.ClientSecret,
  27. RedirectURL: githubRedirectUrl,
  28. Scopes: []string{"user:email"},
  29. }
  30. cfg, err := oauth2.NewConfig(options, githubAuthUrl, githubTokenUrl)
  31. if err != nil {
  32. log.Error("Failed to init github auth %v", err)
  33. }
  34. githubOAuthConfig = cfg
  35. })
  36. }
  37. func (self *HttpServer) oauthGithub(c *gin.Context) {
  38. url := githubOAuthConfig.AuthCodeURL("", "online", "auto")
  39. c.Redirect(302, url)
  40. }
  41. type githubUserInfoDto struct {
  42. Login string `json:"login"`
  43. Name string `json:"name"`
  44. Email string `json:"email"`
  45. Company string `json:"company"`
  46. }
  47. func (self *HttpServer) oauthGithubCallback(c *gin.Context) {
  48. code := c.Request.URL.Query()["code"][0]
  49. log.Info("OAuth code: %v", code)
  50. transport, err := githubOAuthConfig.NewTransportWithCode(code)
  51. if err != nil {
  52. c.String(500, "Failed to exchange oauth token: "+err.Error())
  53. return
  54. }
  55. client := http.Client{Transport: transport}
  56. resp, err := client.Get("https://api.github.com/user")
  57. if err != nil {
  58. c.String(500, err.Error())
  59. return
  60. }
  61. var userInfo githubUserInfoDto
  62. decoder := json.NewDecoder(resp.Body)
  63. err = decoder.Decode(&userInfo)
  64. if err != nil {
  65. c.String(500, err.Error())
  66. return
  67. }
  68. if len(userInfo.Email) < 5 {
  69. c.String(500, "Invalid email")
  70. return
  71. }
  72. // try find existing account
  73. account, err := self.store.GetAccountByLogin(userInfo.Email)
  74. // create account if missing
  75. if err == stores.ErrAccountNotFound {
  76. account = &models.Account{
  77. Login: userInfo.Login,
  78. Email: userInfo.Email,
  79. Name: userInfo.Name,
  80. Company: userInfo.Company,
  81. }
  82. if err = self.store.CreateAccount(account); err != nil {
  83. log.Error("Failed to create account %v", err)
  84. c.String(500, "Failed to create account")
  85. return
  86. }
  87. }
  88. // login
  89. loginUserWithAccount(account, c)
  90. c.Redirect(302, "/")
  91. }