123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- // Copyright 2014 Google Inc. All Rights Reserved.
- // Copyright 2014 The Gogs Authors. All rights reserved.
- // Use of this source code is governed by a MIT-style
- // license that can be found in the LICENSE file.
- 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"}
- // Load all OAuth config data.
- 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)
- // GitHub.
- if setting.Cfg.MustBool("oauth.github", "ENABLED") {
- setting.OauthService.GitHub = true
- newGitHubOauth(socialConfigs["github"])
- enabledOauths = append(enabledOauths, "GitHub")
- }
- // Google.
- if setting.Cfg.MustBool("oauth.google", "ENABLED") {
- setting.OauthService.Google = true
- newGoogleOauth(socialConfigs["google"])
- enabledOauths = append(enabledOauths, "Google")
- }
- // QQ.
- if setting.Cfg.MustBool("oauth.qq", "ENABLED") {
- setting.OauthService.Tencent = true
- newTencentOauth(socialConfigs["qq"])
- enabledOauths = append(enabledOauths, "QQ")
- }
- // Twitter.
- if setting.Cfg.MustBool("oauth.twitter", "ENABLED") {
- setting.OauthService.Twitter = true
- newTwitterOauth(socialConfigs["twitter"])
- enabledOauths = append(enabledOauths, "Twitter")
- }
- // Weibo.
- 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)
- }
- // ________.__ __ ___ ___ ___.
- // / _____/|__|/ |_ / | \ __ _\_ |__
- // / \ ___| \ __\/ ~ \ | \ __ \
- // \ \_\ \ || | \ Y / | / \_\ \
- // \______ /__||__| \___|_ /|____/|___ /
- // \/ \/ \/
- 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
- // https://open.t.qq.com/api/user/info?
- //oauth_consumer_key=APP_KEY&
- //access_token=ACCESSTOKEN&openid=openid
- //clientip=CLIENTIP&oauth_version=2.a
- //scope=all
- 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
- }
- //https://github.com/mrjones/oauth
- func (s *SocialTwitter) 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
- 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
- }
|