summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/markbates
diff options
context:
space:
mode:
authorLauris BH <lauris@nix.lv>2018-02-19 07:10:51 +0200
committerGitHub <noreply@github.com>2018-02-19 07:10:51 +0200
commit7b297808cee599f5ff58b9f6afa64d3ee980998e (patch)
treeb66509fc7f42094c836c6206d1e4aca12df6cfd6 /vendor/github.com/markbates
parent6f751409b4f996af83e88064877271efa90534f9 (diff)
downloadgitea-7b297808cee599f5ff58b9f6afa64d3ee980998e.tar.gz
gitea-7b297808cee599f5ff58b9f6afa64d3ee980998e.zip
Update markbates/goth library (#3533)
Signed-off-by: Lauris Bukšis-Haberkorns <lauris@nix.lv>
Diffstat (limited to 'vendor/github.com/markbates')
-rw-r--r--vendor/github.com/markbates/goth/README.md97
-rw-r--r--vendor/github.com/markbates/goth/gothic/gothic.go164
-rw-r--r--vendor/github.com/markbates/goth/providers/bitbucket/bitbucket.go12
-rw-r--r--vendor/github.com/markbates/goth/providers/dropbox/dropbox.go21
-rw-r--r--vendor/github.com/markbates/goth/providers/facebook/facebook.go16
-rw-r--r--vendor/github.com/markbates/goth/providers/gitlab/gitlab.go2
-rw-r--r--vendor/github.com/markbates/goth/providers/gplus/gplus.go10
-rw-r--r--vendor/github.com/markbates/goth/providers/openidConnect/openidConnect.go30
-rw-r--r--vendor/github.com/markbates/goth/providers/openidConnect/session.go4
-rw-r--r--vendor/github.com/markbates/goth/providers/twitter/twitter.go24
10 files changed, 252 insertions, 128 deletions
diff --git a/vendor/github.com/markbates/goth/README.md b/vendor/github.com/markbates/goth/README.md
index b481683bcc..05b19fce5a 100644
--- a/vendor/github.com/markbates/goth/README.md
+++ b/vendor/github.com/markbates/goth/README.md
@@ -8,6 +8,10 @@ protocol providers, as long as they implement the `Provider` and `Session` inter
This package was inspired by [https://github.com/intridea/omniauth](https://github.com/intridea/omniauth).
+## Goth Needs a New Maintainer
+
+[https://blog.gobuffalo.io/goth-needs-a-new-maintainer-626cd47ca37b](https://blog.gobuffalo.io/goth-needs-a-new-maintainer-626cd47ca37b) - TL;DR: I, @markbates, won't be responding to any more issues, PRs, etc... for this package. A new maintainer needs to be found ASAP. Is this you?
+
## Installation
```text
@@ -18,6 +22,8 @@ $ go get github.com/markbates/goth
* Amazon
* Auth0
+* Azure AD
+* Battle.net
* Bitbucket
* Box
* Cloud Foundry
@@ -26,6 +32,7 @@ $ go get github.com/markbates/goth
* Digital Ocean
* Discord
* Dropbox
+* Eve Online
* Facebook
* Fitbit
* GitHub
@@ -38,6 +45,7 @@ $ go get github.com/markbates/goth
* Lastfm
* Linkedin
* Meetup
+* MicrosoftOnline
* OneDrive
* OpenID Connect (auto discovery)
* Paypal
@@ -50,7 +58,9 @@ $ go get github.com/markbates/goth
* Twitch
* Twitter
* Uber
+* VK
* Wepay
+* Xero
* Yahoo
* Yammer
@@ -71,17 +81,51 @@ $ go get github.com/markbates/goth
```text
$ cd goth/examples
$ go get -v
-$ go build
+$ go build
$ ./examples
```
Now open up your browser and go to [http://localhost:3000](http://localhost:3000) to see the example.
-To actually use the different providers, please make sure you configure them given the system environments as defined in the examples/main.go file
+To actually use the different providers, please make sure you set environment variables. Example given in the examples/main.go file
+
+## Security Notes
+
+By default, gothic uses a `CookieStore` from the `gorilla/sessions` package to store session data.
+
+As configured, this default store (`gothic.Store`) will generate cookies with `Options`:
+
+```go
+&Options{
+ Path: "/",
+ Domain: "",
+ MaxAge: 86400 * 30,
+ HttpOnly: true,
+ Secure: false,
+ }
+```
+
+To tailor these fields for your application, you can override the `gothic.Store` variable at startup.
+
+The follow snippet show one way to do this:
+
+```go
+key := "" // Replace with your SESSION_SECRET or similar
+maxAge := 86400 * 30 // 30 days
+isProd := false // Set to true when serving over https
+
+store := sessions.NewCookieStore([]byte(key))
+store.MaxAge(maxAge)
+store.Options.Path = "/"
+store.Options.HttpOnly = true // HttpOnly should always be enabled
+store.Options.Secure = isProd
+
+gothic.Store = store
+```
## Issues
-Issues always stand a significantly better chance of getting fixed if the are accompanied by a
+Issues always stand a significantly better chance of getting fixed if they are accompanied by a
pull request.
## Contributing
@@ -94,50 +138,3 @@ Would I love to see more providers? Certainly! Would you love to contribute one?
4. Commit your changes (git commit -am 'Add some feature')
5. Push to the branch (git push origin my-new-feature)
6. Create new Pull Request
-
-## Contributors
-
-* Mark Bates
-* Tyler Bunnell
-* Corey McGrillis
-* willemvd
-* Rakesh Goyal
-* Andy Grunwald
-* Glenn Walker
-* Kevin Fitzpatrick
-* Ben Tranter
-* Sharad Ganapathy
-* Andrew Chilton
-* sharadgana
-* Aurorae
-* Craig P Jolicoeur
-* Zac Bergquist
-* Geoff Franks
-* Raphael Geronimi
-* Noah Shibley
-* lumost
-* oov
-* Felix Lamouroux
-* Rafael Quintela
-* Tyler
-* DenSm
-* Samy KACIMI
-* dante gray
-* Noah
-* Jacob Walker
-* Marin Martinic
-* Roy
-* Omni Adams
-* Sasa Brankovic
-* dkhamsing
-* Dante Swift
-* Attila Domokos
-* Albin Gilles
-* Syed Zubairuddin
-* Johnny Boursiquot
-* Jerome Touffe-Blin
-* bryanl
-* Masanobu YOSHIOKA
-* Jonathan Hall
-* HaiMing.Yin
-* Sairam Kunala
diff --git a/vendor/github.com/markbates/goth/gothic/gothic.go b/vendor/github.com/markbates/goth/gothic/gothic.go
index f6aaf2d117..8b8e114940 100644
--- a/vendor/github.com/markbates/goth/gothic/gothic.go
+++ b/vendor/github.com/markbates/goth/gothic/gothic.go
@@ -8,10 +8,18 @@ See https://github.com/markbates/goth/examples/main.go to see this in action.
package gothic
import (
+ "bytes"
+ "compress/gzip"
+ "encoding/base64"
"errors"
"fmt"
+ "io/ioutil"
+ "math/rand"
"net/http"
+ "net/url"
"os"
+ "strings"
+ "time"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
@@ -27,15 +35,21 @@ var defaultStore sessions.Store
var keySet = false
+var gothicRand *rand.Rand
+
func init() {
key := []byte(os.Getenv("SESSION_SECRET"))
keySet = len(key) != 0
- Store = sessions.NewCookieStore([]byte(key))
+
+ cookieStore := sessions.NewCookieStore([]byte(key))
+ cookieStore.Options.HttpOnly = true
+ Store = cookieStore
defaultStore = Store
+ gothicRand = rand.New(rand.NewSource(time.Now().UnixNano()))
}
/*
-BeginAuthHandler is a convienence handler for starting the authentication process.
+BeginAuthHandler is a convenience handler for starting the authentication process.
It expects to be able to get the name of the provider from the query parameters
as either "provider" or ":provider".
@@ -65,8 +79,16 @@ var SetState = func(req *http.Request) string {
return state
}
- return "state"
-
+ // If a state query param is not passed in, generate a random
+ // base64-encoded nonce so that the state on the auth URL
+ // is unguessable, preventing CSRF attacks, as described in
+ //
+ // https://auth0.com/docs/protocols/oauth2/oauth-state#keep-reading
+ nonceBytes := make([]byte, 64)
+ for i := 0; i < 64; i++ {
+ nonceBytes[i] = byte(gothicRand.Int63() % 256)
+ }
+ return base64.URLEncoding.EncodeToString(nonceBytes)
}
// GetState gets the state returned by the provider during the callback.
@@ -87,7 +109,6 @@ I would recommend using the BeginAuthHandler instead of doing all of these steps
yourself, but that's entirely up to you.
*/
func GetAuthURL(res http.ResponseWriter, req *http.Request) (string, error) {
-
if !keySet && defaultStore == Store {
fmt.Println("goth/gothic: no SESSION_SECRET environment variable is set. The default cookie store is not available and any calls will fail. Ignore this warning if you are using a different store.")
}
@@ -130,7 +151,7 @@ as either "provider" or ":provider".
See https://github.com/markbates/goth/examples/main.go to see this in action.
*/
var CompleteUserAuth = func(res http.ResponseWriter, req *http.Request) (goth.User, error) {
-
+ defer Logout(res, req)
if !keySet && defaultStore == Store {
fmt.Println("goth/gothic: no SESSION_SECRET environment variable is set. The default cookie store is not available and any calls will fail. Ignore this warning if you are using a different store.")
}
@@ -155,6 +176,11 @@ var CompleteUserAuth = func(res http.ResponseWriter, req *http.Request) (goth.Us
return goth.User{}, err
}
+ err = validateState(req, sess)
+ if err != nil {
+ return goth.User{}, err
+ }
+
user, err := provider.FetchUser(sess)
if err == nil {
// user can be found with existing session data
@@ -173,7 +199,43 @@ var CompleteUserAuth = func(res http.ResponseWriter, req *http.Request) (goth.Us
return goth.User{}, err
}
- return provider.FetchUser(sess)
+ gu, err := provider.FetchUser(sess)
+ return gu, err
+}
+
+// validateState ensures that the state token param from the original
+// AuthURL matches the one included in the current (callback) request.
+func validateState(req *http.Request, sess goth.Session) error {
+ rawAuthURL, err := sess.GetAuthURL()
+ if err != nil {
+ return err
+ }
+
+ authURL, err := url.Parse(rawAuthURL)
+ if err != nil {
+ return err
+ }
+
+ originalState := authURL.Query().Get("state")
+ if originalState != "" && (originalState != req.URL.Query().Get("state")) {
+ return errors.New("state token mismatch")
+ }
+ return nil
+}
+
+// Logout invalidates a user session.
+func Logout(res http.ResponseWriter, req *http.Request) error {
+ session, err := Store.Get(req, SessionName)
+ if err != nil {
+ return err
+ }
+ session.Options.MaxAge = -1
+ session.Values = make(map[interface{}]interface{})
+ err = session.Save(req, res)
+ if err != nil {
+ return errors.New("Could not delete user session ")
+ }
+ return nil
}
// GetProviderName is a function used to get the name of a provider
@@ -184,36 +246,96 @@ var CompleteUserAuth = func(res http.ResponseWriter, req *http.Request) (goth.Us
var GetProviderName = getProviderName
func getProviderName(req *http.Request) (string, error) {
- provider := req.URL.Query().Get("provider")
- if provider == "" {
- if p, ok := mux.Vars(req)["provider"]; ok {
+
+ // get all the used providers
+ providers := goth.GetProviders()
+
+ // loop over the used providers, if we already have a valid session for any provider (ie. user is already logged-in with a provider), then return that provider name
+ for _, provider := range providers {
+ p := provider.Name()
+ session, _ := Store.Get(req, p+SessionName)
+ value := session.Values[p]
+ if _, ok := value.(string); ok {
return p, nil
}
}
- if provider == "" {
- provider = req.URL.Query().Get(":provider")
+
+ // try to get it from the url param "provider"
+ if p := req.URL.Query().Get("provider"); p != "" {
+ return p, nil
}
- if provider == "" {
- return provider, errors.New("you must select a provider")
+
+ // try to get it from the url param ":provider"
+ if p := req.URL.Query().Get(":provider"); p != "" {
+ return p, nil
+ }
+
+ // try to get it from the context's value of "provider" key
+ if p, ok := mux.Vars(req)["provider"]; ok {
+ return p, nil
}
- return provider, nil
+
+ // try to get it from the go-context's value of "provider" key
+ if p, ok := req.Context().Value("provider").(string); ok {
+ return p, nil
+ }
+
+ // if not found then return an empty string with the corresponding error
+ return "", errors.New("you must select a provider")
}
func storeInSession(key string, value string, req *http.Request, res http.ResponseWriter) error {
- session, _ := Store.Get(req, key + SessionName)
+ session, _ := Store.Get(req, SessionName)
- session.Values[key] = value
+ if err := updateSessionValue(session, key, value); err != nil {
+ return err
+ }
return session.Save(req, res)
}
func getFromSession(key string, req *http.Request) (string, error) {
- session, _ := Store.Get(req, key + SessionName)
+ session, _ := Store.Get(req, SessionName)
+ value, err := getSessionValue(session, key)
+ if err != nil {
+ return "", errors.New("could not find a matching session for this request")
+ }
+ return value, nil
+}
+
+func getSessionValue(session *sessions.Session, key string) (string, error) {
value := session.Values[key]
if value == nil {
- return "", errors.New("could not find a matching session for this request")
+ return "", fmt.Errorf("could not find a matching session for this request")
}
- return value.(string), nil
-} \ No newline at end of file
+ rdata := strings.NewReader(value.(string))
+ r, err := gzip.NewReader(rdata)
+ if err != nil {
+ return "", err
+ }
+ s, err := ioutil.ReadAll(r)
+ if err != nil {
+ return "", err
+ }
+
+ return string(s), nil
+}
+
+func updateSessionValue(session *sessions.Session, key, value string) error {
+ var b bytes.Buffer
+ gz := gzip.NewWriter(&b)
+ if _, err := gz.Write([]byte(value)); err != nil {
+ return err
+ }
+ if err := gz.Flush(); err != nil {
+ return err
+ }
+ if err := gz.Close(); err != nil {
+ return err
+ }
+
+ session.Values[key] = b.String()
+ return nil
+}
diff --git a/vendor/github.com/markbates/goth/providers/bitbucket/bitbucket.go b/vendor/github.com/markbates/goth/providers/bitbucket/bitbucket.go
index 06d9c923cb..c19734770d 100644
--- a/vendor/github.com/markbates/goth/providers/bitbucket/bitbucket.go
+++ b/vendor/github.com/markbates/goth/providers/bitbucket/bitbucket.go
@@ -9,9 +9,9 @@ import (
"net/http"
"net/url"
+ "fmt"
"github.com/markbates/goth"
"golang.org/x/oauth2"
- "fmt"
)
const (
@@ -26,10 +26,10 @@ const (
// one manually.
func New(clientKey, secret, callbackURL string, scopes ...string) *Provider {
p := &Provider{
- ClientKey: clientKey,
- Secret: secret,
- CallbackURL: callbackURL,
- providerName: "bitbucket",
+ ClientKey: clientKey,
+ Secret: secret,
+ CallbackURL: callbackURL,
+ providerName: "bitbucket",
}
p.config = newConfig(p, scopes)
return p
@@ -125,7 +125,7 @@ func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
func userFromReader(reader io.Reader, user *goth.User) error {
u := struct {
- ID string `json:"uuid"`
+ ID string `json:"uuid"`
Links struct {
Avatar struct {
URL string `json:"href"`
diff --git a/vendor/github.com/markbates/goth/providers/dropbox/dropbox.go b/vendor/github.com/markbates/goth/providers/dropbox/dropbox.go
index 61533d405e..262905806b 100644
--- a/vendor/github.com/markbates/goth/providers/dropbox/dropbox.go
+++ b/vendor/github.com/markbates/goth/providers/dropbox/dropbox.go
@@ -8,15 +8,16 @@ import (
"net/http"
"strings"
+ "fmt"
+
"github.com/markbates/goth"
"golang.org/x/oauth2"
- "fmt"
)
const (
- authURL = "https://www.dropbox.com/1/oauth2/authorize"
- tokenURL = "https://api.dropbox.com/1/oauth2/token"
- accountURL = "https://api.dropbox.com/1/account/info"
+ authURL = "https://www.dropbox.com/oauth2/authorize"
+ tokenURL = "https://api.dropbox.com/oauth2/token"
+ accountURL = "https://api.dropbox.com/2/users/get_current_account"
)
// Provider is the implementation of `goth.Provider` for accessing Dropbox.
@@ -40,10 +41,10 @@ type Session struct {
// create one manually.
func New(clientKey, secret, callbackURL string, scopes ...string) *Provider {
p := &Provider{
- ClientKey: clientKey,
- Secret: secret,
- CallbackURL: callbackURL,
- providerName: "dropbox",
+ ClientKey: clientKey,
+ Secret: secret,
+ CallbackURL: callbackURL,
+ providerName: "dropbox",
}
p.config = newConfig(p, scopes)
return p
@@ -86,7 +87,7 @@ func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
return user, fmt.Errorf("%s cannot get user information without accessToken", p.providerName)
}
- req, err := http.NewRequest("GET", accountURL, nil)
+ req, err := http.NewRequest("POST", accountURL, nil)
if err != nil {
return user, err
}
@@ -161,7 +162,7 @@ func newConfig(p *Provider, scopes []string) *oauth2.Config {
func userFromReader(r io.Reader, user *goth.User) error {
u := struct {
- Name string `json:"display_name"`
+ Name string `json:"display_name"`
NameDetails struct {
NickName string `json:"familiar_name"`
} `json:"name_details"`
diff --git a/vendor/github.com/markbates/goth/providers/facebook/facebook.go b/vendor/github.com/markbates/goth/providers/facebook/facebook.go
index e0cfdf1e34..266bbe2208 100644
--- a/vendor/github.com/markbates/goth/providers/facebook/facebook.go
+++ b/vendor/github.com/markbates/goth/providers/facebook/facebook.go
@@ -11,12 +11,12 @@ import (
"net/http"
"net/url"
- "github.com/markbates/goth"
- "golang.org/x/oauth2"
- "fmt"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
+ "fmt"
+ "github.com/markbates/goth"
+ "golang.org/x/oauth2"
)
const (
@@ -30,10 +30,10 @@ const (
// one manually.
func New(clientKey, secret, callbackURL string, scopes ...string) *Provider {
p := &Provider{
- ClientKey: clientKey,
- Secret: secret,
- CallbackURL: callbackURL,
- providerName: "facebook",
+ ClientKey: clientKey,
+ Secret: secret,
+ CallbackURL: callbackURL,
+ providerName: "facebook",
}
p.config = newConfig(p, scopes)
return p
@@ -129,7 +129,7 @@ func userFromReader(reader io.Reader, user *goth.User) error {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Link string `json:"link"`
- Picture struct {
+ Picture struct {
Data struct {
URL string `json:"url"`
} `json:"data"`
diff --git a/vendor/github.com/markbates/goth/providers/gitlab/gitlab.go b/vendor/github.com/markbates/goth/providers/gitlab/gitlab.go
index fe188c01a9..533632e7fd 100644
--- a/vendor/github.com/markbates/goth/providers/gitlab/gitlab.go
+++ b/vendor/github.com/markbates/goth/providers/gitlab/gitlab.go
@@ -11,9 +11,9 @@ import (
"net/url"
"strconv"
+ "fmt"
"github.com/markbates/goth"
"golang.org/x/oauth2"
- "fmt"
)
// These vars define the Authentication, Token, and Profile URLS for Gitlab. If
diff --git a/vendor/github.com/markbates/goth/providers/gplus/gplus.go b/vendor/github.com/markbates/goth/providers/gplus/gplus.go
index 06655c2f7f..4726aa349e 100644
--- a/vendor/github.com/markbates/goth/providers/gplus/gplus.go
+++ b/vendor/github.com/markbates/goth/providers/gplus/gplus.go
@@ -11,9 +11,9 @@ import (
"net/url"
"strings"
+ "fmt"
"github.com/markbates/goth"
"golang.org/x/oauth2"
- "fmt"
)
const (
@@ -27,10 +27,10 @@ const (
// one manually.
func New(clientKey, secret, callbackURL string, scopes ...string) *Provider {
p := &Provider{
- ClientKey: clientKey,
- Secret: secret,
- CallbackURL: callbackURL,
- providerName: "gplus",
+ ClientKey: clientKey,
+ Secret: secret,
+ CallbackURL: callbackURL,
+ providerName: "gplus",
}
p.config = newConfig(p, scopes)
return p
diff --git a/vendor/github.com/markbates/goth/providers/openidConnect/openidConnect.go b/vendor/github.com/markbates/goth/providers/openidConnect/openidConnect.go
index 7ffd11c607..44419ba15f 100644
--- a/vendor/github.com/markbates/goth/providers/openidConnect/openidConnect.go
+++ b/vendor/github.com/markbates/goth/providers/openidConnect/openidConnect.go
@@ -1,17 +1,17 @@
package openidConnect
import (
- "net/http"
- "strings"
- "fmt"
- "encoding/json"
+ "bytes"
"encoding/base64"
- "io/ioutil"
+ "encoding/json"
"errors"
- "golang.org/x/oauth2"
+ "fmt"
"github.com/markbates/goth"
+ "golang.org/x/oauth2"
+ "io/ioutil"
+ "net/http"
+ "strings"
"time"
- "bytes"
)
const (
@@ -89,14 +89,14 @@ func New(clientKey, secret, callbackURL, openIDAutoDiscoveryURL string, scopes .
Secret: secret,
CallbackURL: callbackURL,
- UserIdClaims: []string{subjectClaim},
- NameClaims: []string{NameClaim},
- NickNameClaims: []string{NicknameClaim, PreferredUsernameClaim},
- EmailClaims: []string{EmailClaim},
- AvatarURLClaims:[]string{PictureClaim},
- FirstNameClaims:[]string{GivenNameClaim},
- LastNameClaims: []string{FamilyNameClaim},
- LocationClaims: []string{AddressClaim},
+ UserIdClaims: []string{subjectClaim},
+ NameClaims: []string{NameClaim},
+ NickNameClaims: []string{NicknameClaim, PreferredUsernameClaim},
+ EmailClaims: []string{EmailClaim},
+ AvatarURLClaims: []string{PictureClaim},
+ FirstNameClaims: []string{GivenNameClaim},
+ LastNameClaims: []string{FamilyNameClaim},
+ LocationClaims: []string{AddressClaim},
providerName: "openid-connect",
}
diff --git a/vendor/github.com/markbates/goth/providers/openidConnect/session.go b/vendor/github.com/markbates/goth/providers/openidConnect/session.go
index a34584fdef..d223cf8752 100644
--- a/vendor/github.com/markbates/goth/providers/openidConnect/session.go
+++ b/vendor/github.com/markbates/goth/providers/openidConnect/session.go
@@ -1,12 +1,12 @@
package openidConnect
import (
+ "encoding/json"
"errors"
"github.com/markbates/goth"
- "encoding/json"
+ "golang.org/x/oauth2"
"strings"
"time"
- "golang.org/x/oauth2"
)
// Session stores data during the auth process with the OpenID Connect provider.
diff --git a/vendor/github.com/markbates/goth/providers/twitter/twitter.go b/vendor/github.com/markbates/goth/providers/twitter/twitter.go
index 3703f21974..2ce20e780e 100644
--- a/vendor/github.com/markbates/goth/providers/twitter/twitter.go
+++ b/vendor/github.com/markbates/goth/providers/twitter/twitter.go
@@ -9,10 +9,11 @@ import (
"io/ioutil"
"net/http"
+ "fmt"
+
"github.com/markbates/goth"
"github.com/mrjones/oauth"
"golang.org/x/oauth2"
- "fmt"
)
var (
@@ -30,10 +31,10 @@ var (
// If you'd like to use authenticate instead of authorize, use NewAuthenticate instead.
func New(clientKey, secret, callbackURL string) *Provider {
p := &Provider{
- ClientKey: clientKey,
- Secret: secret,
- CallbackURL: callbackURL,
- providerName: "twitter",
+ ClientKey: clientKey,
+ Secret: secret,
+ CallbackURL: callbackURL,
+ providerName: "twitter",
}
p.consumer = newConsumer(p, authorizeURL)
return p
@@ -43,10 +44,10 @@ func New(clientKey, secret, callbackURL string) *Provider {
// NewAuthenticate uses the authenticate URL instead of the authorize URL.
func NewAuthenticate(clientKey, secret, callbackURL string) *Provider {
p := &Provider{
- ClientKey: clientKey,
- Secret: secret,
- CallbackURL: callbackURL,
- providerName: "twitter",
+ ClientKey: clientKey,
+ Secret: secret,
+ CallbackURL: callbackURL,
+ providerName: "twitter",
}
p.consumer = newConsumer(p, authenticateURL)
return p
@@ -107,7 +108,7 @@ func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
response, err := p.consumer.Get(
endpointProfile,
- map[string]string{"include_entities": "false", "skip_status": "true"},
+ map[string]string{"include_entities": "false", "skip_status": "true", "include_email": "true"},
sess.AccessToken)
if err != nil {
return user, err
@@ -126,6 +127,9 @@ func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
user.Name = user.RawData["name"].(string)
user.NickName = user.RawData["screen_name"].(string)
+ if user.RawData["email"] != nil {
+ user.Email = user.RawData["email"].(string)
+ }
user.Description = user.RawData["description"].(string)
user.AvatarURL = user.RawData["profile_image_url"].(string)
user.UserID = user.RawData["id_str"].(string)