123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- package social
- import (
- "encoding/json"
- "net/http"
- "net/url"
- "strconv"
- "strings"
- oauth "github.com/gogits/oauth2"
- "github.com/gogits/gogs/models"
- "github.com/gogits/gogs/modules/log"
- "github.com/gogits/gogs/modules/setting"
- )
- type BasicUserInfo struct {
- Identity string
- Name string
- Email string
- }
- type SocialConnector interface {
- Type() int
- SetRedirectUrl(string)
- UserInfo(*oauth.Token, *url.URL) (*BasicUserInfo, error)
- AuthCodeURL(string) string
- Exchange(string) (*oauth.Token, error)
- }
- var (
- SocialBaseUrl = "/user/login"
- SocialMap = make(map[string]SocialConnector)
- )
- func NewOauthService() {
- if !setting.Cfg.MustBool("oauth", "ENABLED") {
- return
- }
- setting.OauthService = &setting.Oauther{}
- setting.OauthService.OauthInfos = make(map[string]*setting.OauthInfo)
- socialConfigs := make(map[string]*oauth.Config)
- allOauthes := []string{"github", "google", "qq", "twitter", "weibo"}
-
- for _, name := range allOauthes {
- setting.OauthService.OauthInfos[name] = &setting.OauthInfo{
- ClientId: setting.Cfg.MustValue("oauth."+name, "CLIENT_ID"),
- ClientSecret: setting.Cfg.MustValue("oauth."+name, "CLIENT_SECRET"),
- Scopes: setting.Cfg.MustValue("oauth."+name, "SCOPES"),
- AuthUrl: setting.Cfg.MustValue("oauth."+name, "AUTH_URL"),
- TokenUrl: setting.Cfg.MustValue("oauth."+name, "TOKEN_URL"),
- }
- socialConfigs[name] = &oauth.Config{
- ClientId: setting.OauthService.OauthInfos[name].ClientId,
- ClientSecret: setting.OauthService.OauthInfos[name].ClientSecret,
- RedirectURL: strings.TrimSuffix(setting.AppUrl, "/") + SocialBaseUrl + name,
- Scope: setting.OauthService.OauthInfos[name].Scopes,
- AuthURL: setting.OauthService.OauthInfos[name].AuthUrl,
- TokenURL: setting.OauthService.OauthInfos[name].TokenUrl,
- }
- }
- enabledOauths := make([]string, 0, 10)
-
- if setting.Cfg.MustBool("oauth.github", "ENABLED") {
- setting.OauthService.GitHub = true
- newGitHubOauth(socialConfigs["github"])
- enabledOauths = append(enabledOauths, "GitHub")
- }
-
- if setting.Cfg.MustBool("oauth.google", "ENABLED") {
- setting.OauthService.Google = true
- newGoogleOauth(socialConfigs["google"])
- enabledOauths = append(enabledOauths, "Google")
- }
-
- if setting.Cfg.MustBool("oauth.qq", "ENABLED") {
- setting.OauthService.Tencent = true
- newTencentOauth(socialConfigs["qq"])
- enabledOauths = append(enabledOauths, "QQ")
- }
-
- if setting.Cfg.MustBool("oauth.twitter", "ENABLED") {
- setting.OauthService.Twitter = true
- newTwitterOauth(socialConfigs["twitter"])
- enabledOauths = append(enabledOauths, "Twitter")
- }
-
- if setting.Cfg.MustBool("oauth.weibo", "ENABLED") {
- setting.OauthService.Weibo = true
- newWeiboOauth(socialConfigs["weibo"])
- enabledOauths = append(enabledOauths, "Weibo")
- }
- log.Info("Oauth Service Enabled %s", enabledOauths)
- }
- type SocialGithub struct {
- Token *oauth.Token
- *oauth.Transport
- }
- func (s *SocialGithub) Type() int {
- return int(models.GITHUB)
- }
- func newGitHubOauth(config *oauth.Config) {
- SocialMap["github"] = &SocialGithub{
- Transport: &oauth.Transport{
- Config: config,
- Transport: http.DefaultTransport,
- },
- }
- }
- func (s *SocialGithub) SetRedirectUrl(url string) {
- s.Transport.Config.RedirectURL = url
- }
- func (s *SocialGithub) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
- transport := &oauth.Transport{
- Token: token,
- }
- var data struct {
- Id int `json:"id"`
- Name string `json:"login"`
- Email string `json:"email"`
- }
- var err error
- r, err := transport.Client().Get(s.Transport.Scope)
- if err != nil {
- return nil, err
- }
- defer r.Body.Close()
- if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
- return nil, err
- }
- return &BasicUserInfo{
- Identity: strconv.Itoa(data.Id),
- Name: data.Name,
- Email: data.Email,
- }, nil
- }
- type SocialGoogle struct {
- Token *oauth.Token
- *oauth.Transport
- }
- func (s *SocialGoogle) Type() int {
- return int(models.GOOGLE)
- }
- func newGoogleOauth(config *oauth.Config) {
- SocialMap["google"] = &SocialGoogle{
- Transport: &oauth.Transport{
- Config: config,
- Transport: http.DefaultTransport,
- },
- }
- }
- func (s *SocialGoogle) SetRedirectUrl(url string) {
- s.Transport.Config.RedirectURL = url
- }
- func (s *SocialGoogle) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
- transport := &oauth.Transport{Token: token}
- var data struct {
- Id string `json:"id"`
- Name string `json:"name"`
- Email string `json:"email"`
- }
- var err error
- reqUrl := "https://www.googleapis.com/oauth2/v1/userinfo"
- r, err := transport.Client().Get(reqUrl)
- if err != nil {
- return nil, err
- }
- defer r.Body.Close()
- if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
- return nil, err
- }
- return &BasicUserInfo{
- Identity: data.Id,
- Name: data.Name,
- Email: data.Email,
- }, nil
- }
- type SocialTencent struct {
- Token *oauth.Token
- *oauth.Transport
- reqUrl string
- }
- func (s *SocialTencent) Type() int {
- return int(models.QQ)
- }
- func newTencentOauth(config *oauth.Config) {
- SocialMap["qq"] = &SocialTencent{
- reqUrl: "https://open.t.qq.com/api/user/info",
- Transport: &oauth.Transport{
- Config: config,
- Transport: http.DefaultTransport,
- },
- }
- }
- func (s *SocialTencent) SetRedirectUrl(url string) {
- s.Transport.Config.RedirectURL = url
- }
- func (s *SocialTencent) UserInfo(token *oauth.Token, URL *url.URL) (*BasicUserInfo, error) {
- var data struct {
- Data struct {
- Id string `json:"openid"`
- Name string `json:"name"`
- Email string `json:"email"`
- } `json:"data"`
- }
- var err error
-
-
-
-
-
- var urls = url.Values{
- "oauth_consumer_key": {s.Transport.Config.ClientId},
- "access_token": {token.AccessToken},
- "openid": URL.Query()["openid"],
- "oauth_version": {"2.a"},
- "scope": {"all"},
- }
- r, err := http.Get(s.reqUrl + "?" + urls.Encode())
- if err != nil {
- return nil, err
- }
- defer r.Body.Close()
- if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
- return nil, err
- }
- return &BasicUserInfo{
- Identity: data.Data.Id,
- Name: data.Data.Name,
- Email: data.Data.Email,
- }, nil
- }
- type SocialTwitter struct {
- Token *oauth.Token
- *oauth.Transport
- }
- func (s *SocialTwitter) Type() int {
- return int(models.TWITTER)
- }
- func newTwitterOauth(config *oauth.Config) {
- SocialMap["twitter"] = &SocialTwitter{
- Transport: &oauth.Transport{
- Config: config,
- Transport: http.DefaultTransport,
- },
- }
- }
- func (s *SocialTwitter) SetRedirectUrl(url string) {
- s.Transport.Config.RedirectURL = url
- }
- func (s *SocialTwitter) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- return nil, nil
- }
- type SocialWeibo struct {
- Token *oauth.Token
- *oauth.Transport
- }
- func (s *SocialWeibo) Type() int {
- return int(models.WEIBO)
- }
- func newWeiboOauth(config *oauth.Config) {
- SocialMap["weibo"] = &SocialWeibo{
- Transport: &oauth.Transport{
- Config: config,
- Transport: http.DefaultTransport,
- },
- }
- }
- func (s *SocialWeibo) SetRedirectUrl(url string) {
- s.Transport.Config.RedirectURL = url
- }
- func (s *SocialWeibo) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
- transport := &oauth.Transport{Token: token}
- var data struct {
- Name string `json:"name"`
- }
- var err error
- var urls = url.Values{
- "access_token": {token.AccessToken},
- "uid": {token.Extra["id_token"]},
- }
- reqUrl := "https://api.weibo.com/2/users/show.json"
- r, err := transport.Client().Get(reqUrl + "?" + urls.Encode())
- if err != nil {
- return nil, err
- }
- defer r.Body.Close()
- if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
- return nil, err
- }
- return &BasicUserInfo{
- Identity: token.Extra["id_token"],
- Name: data.Name,
- }, nil
- }
|