summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/markbates
diff options
context:
space:
mode:
authorWillem van Dreumel <willemvd@users.noreply.github.com>2017-02-22 08:14:37 +0100
committerKim "BKC" Carlbäcker <kim.carlbacker@gmail.com>2017-02-22 08:14:37 +0100
commit01d957677f160e4b5e43ce043b05e246493b34ea (patch)
treee06e3849d874ce37f02b29666ada6069b78decd9 /vendor/github.com/markbates
parentfd941db246e66244ec81f43d74b8358c06173fd6 (diff)
downloadgitea-01d957677f160e4b5e43ce043b05e246493b34ea.tar.gz
gitea-01d957677f160e4b5e43ce043b05e246493b34ea.zip
Oauth2 consumer (#679)
* initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
Diffstat (limited to 'vendor/github.com/markbates')
-rw-r--r--vendor/github.com/markbates/goth/LICENSE.txt22
-rw-r--r--vendor/github.com/markbates/goth/README.md143
-rw-r--r--vendor/github.com/markbates/goth/doc.go10
-rw-r--r--vendor/github.com/markbates/goth/gothic/gothic.go219
-rw-r--r--vendor/github.com/markbates/goth/provider.go75
-rw-r--r--vendor/github.com/markbates/goth/providers/github/github.go224
-rw-r--r--vendor/github.com/markbates/goth/providers/github/session.go56
-rw-r--r--vendor/github.com/markbates/goth/session.go21
-rw-r--r--vendor/github.com/markbates/goth/user.go30
9 files changed, 800 insertions, 0 deletions
diff --git a/vendor/github.com/markbates/goth/LICENSE.txt b/vendor/github.com/markbates/goth/LICENSE.txt
new file mode 100644
index 0000000000..f8e6d5b27f
--- /dev/null
+++ b/vendor/github.com/markbates/goth/LICENSE.txt
@@ -0,0 +1,22 @@
+Copyright (c) 2014 Mark Bates
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/github.com/markbates/goth/README.md b/vendor/github.com/markbates/goth/README.md
new file mode 100644
index 0000000000..b481683bcc
--- /dev/null
+++ b/vendor/github.com/markbates/goth/README.md
@@ -0,0 +1,143 @@
+# Goth: Multi-Provider Authentication for Go [![GoDoc](https://godoc.org/github.com/markbates/goth?status.svg)](https://godoc.org/github.com/markbates/goth) [![Build Status](https://travis-ci.org/markbates/goth.svg)](https://travis-ci.org/markbates/goth)
+
+Package goth provides a simple, clean, and idiomatic way to write authentication
+packages for Go web applications.
+
+Unlike other similar packages, Goth, lets you write OAuth, OAuth2, or any other
+protocol providers, as long as they implement the `Provider` and `Session` interfaces.
+
+This package was inspired by [https://github.com/intridea/omniauth](https://github.com/intridea/omniauth).
+
+## Installation
+
+```text
+$ go get github.com/markbates/goth
+```
+
+## Supported Providers
+
+* Amazon
+* Auth0
+* Bitbucket
+* Box
+* Cloud Foundry
+* Dailymotion
+* Deezer
+* Digital Ocean
+* Discord
+* Dropbox
+* Facebook
+* Fitbit
+* GitHub
+* Gitlab
+* Google+
+* Heroku
+* InfluxCloud
+* Instagram
+* Intercom
+* Lastfm
+* Linkedin
+* Meetup
+* OneDrive
+* OpenID Connect (auto discovery)
+* Paypal
+* SalesForce
+* Slack
+* Soundcloud
+* Spotify
+* Steam
+* Stripe
+* Twitch
+* Twitter
+* Uber
+* Wepay
+* Yahoo
+* Yammer
+
+## Examples
+
+See the [examples](examples) folder for a working application that lets users authenticate
+through Twitter, Facebook, Google Plus etc.
+
+To run the example either clone the source from GitHub
+
+```text
+$ git clone git@github.com:markbates/goth.git
+```
+or use
+```text
+$ go get github.com/markbates/goth
+```
+```text
+$ cd goth/examples
+$ go get -v
+$ 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
+
+## Issues
+
+Issues always stand a significantly better chance of getting fixed if the are accompanied by a
+pull request.
+
+## Contributing
+
+Would I love to see more providers? Certainly! Would you love to contribute one? Hopefully, yes!
+
+1. Fork it
+2. Create your feature branch (git checkout -b my-new-feature)
+3. Write Tests!
+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/doc.go b/vendor/github.com/markbates/goth/doc.go
new file mode 100644
index 0000000000..d0bec281c1
--- /dev/null
+++ b/vendor/github.com/markbates/goth/doc.go
@@ -0,0 +1,10 @@
+/*
+Package goth provides a simple, clean, and idiomatic way to write authentication
+packages for Go web applications.
+
+This package was inspired by https://github.com/intridea/omniauth.
+
+See the examples folder for a working application that lets users authenticate
+through Twitter or Facebook.
+*/
+package goth
diff --git a/vendor/github.com/markbates/goth/gothic/gothic.go b/vendor/github.com/markbates/goth/gothic/gothic.go
new file mode 100644
index 0000000000..f6aaf2d117
--- /dev/null
+++ b/vendor/github.com/markbates/goth/gothic/gothic.go
@@ -0,0 +1,219 @@
+/*
+Package gothic wraps common behaviour when using Goth. This makes it quick, and easy, to get up
+and running with Goth. Of course, if you want complete control over how things flow, in regards
+to the authentication process, feel free and use Goth directly.
+
+See https://github.com/markbates/goth/examples/main.go to see this in action.
+*/
+package gothic
+
+import (
+ "errors"
+ "fmt"
+ "net/http"
+ "os"
+
+ "github.com/gorilla/mux"
+ "github.com/gorilla/sessions"
+ "github.com/markbates/goth"
+)
+
+// SessionName is the key used to access the session store.
+const SessionName = "_gothic_session"
+
+// Store can/should be set by applications using gothic. The default is a cookie store.
+var Store sessions.Store
+var defaultStore sessions.Store
+
+var keySet = false
+
+func init() {
+ key := []byte(os.Getenv("SESSION_SECRET"))
+ keySet = len(key) != 0
+ Store = sessions.NewCookieStore([]byte(key))
+ defaultStore = Store
+}
+
+/*
+BeginAuthHandler is a convienence 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".
+
+BeginAuthHandler will redirect the user to the appropriate authentication end-point
+for the requested provider.
+
+See https://github.com/markbates/goth/examples/main.go to see this in action.
+*/
+func BeginAuthHandler(res http.ResponseWriter, req *http.Request) {
+ url, err := GetAuthURL(res, req)
+ if err != nil {
+ res.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintln(res, err)
+ return
+ }
+
+ http.Redirect(res, req, url, http.StatusTemporaryRedirect)
+}
+
+// SetState sets the state string associated with the given request.
+// If no state string is associated with the request, one will be generated.
+// This state is sent to the provider and can be retrieved during the
+// callback.
+var SetState = func(req *http.Request) string {
+ state := req.URL.Query().Get("state")
+ if len(state) > 0 {
+ return state
+ }
+
+ return "state"
+
+}
+
+// GetState gets the state returned by the provider during the callback.
+// This is used to prevent CSRF attacks, see
+// http://tools.ietf.org/html/rfc6749#section-10.12
+var GetState = func(req *http.Request) string {
+ return req.URL.Query().Get("state")
+}
+
+/*
+GetAuthURL starts the authentication process with the requested provided.
+It will return a URL that should be used to send users to.
+
+It expects to be able to get the name of the provider from the query parameters
+as either "provider" or ":provider".
+
+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.")
+ }
+
+ providerName, err := GetProviderName(req)
+ if err != nil {
+ return "", err
+ }
+
+ provider, err := goth.GetProvider(providerName)
+ if err != nil {
+ return "", err
+ }
+ sess, err := provider.BeginAuth(SetState(req))
+ if err != nil {
+ return "", err
+ }
+
+ url, err := sess.GetAuthURL()
+ if err != nil {
+ return "", err
+ }
+
+ err = storeInSession(providerName, sess.Marshal(), req, res)
+
+ if err != nil {
+ return "", err
+ }
+
+ return url, err
+}
+
+/*
+CompleteUserAuth does what it says on the tin. It completes the authentication
+process and fetches all of the basic information about the user from the provider.
+
+It expects to be able to get the name of the provider from the query parameters
+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) {
+
+ 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.")
+ }
+
+ providerName, err := GetProviderName(req)
+ if err != nil {
+ return goth.User{}, err
+ }
+
+ provider, err := goth.GetProvider(providerName)
+ if err != nil {
+ return goth.User{}, err
+ }
+
+ value, err := getFromSession(providerName, req)
+ if err != nil {
+ return goth.User{}, err
+ }
+
+ sess, err := provider.UnmarshalSession(value)
+ if err != nil {
+ return goth.User{}, err
+ }
+
+ user, err := provider.FetchUser(sess)
+ if err == nil {
+ // user can be found with existing session data
+ return user, err
+ }
+
+ // get new token and retry fetch
+ _, err = sess.Authorize(provider, req.URL.Query())
+ if err != nil {
+ return goth.User{}, err
+ }
+
+ err = storeInSession(providerName, sess.Marshal(), req, res)
+
+ if err != nil {
+ return goth.User{}, err
+ }
+
+ return provider.FetchUser(sess)
+}
+
+// GetProviderName is a function used to get the name of a provider
+// for a given request. By default, this provider is fetched from
+// the URL query string. If you provide it in a different way,
+// assign your own function to this variable that returns the provider
+// name for your request.
+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 {
+ return p, nil
+ }
+ }
+ if provider == "" {
+ provider = req.URL.Query().Get(":provider")
+ }
+ if provider == "" {
+ return provider, errors.New("you must select a provider")
+ }
+ return provider, nil
+}
+
+func storeInSession(key string, value string, req *http.Request, res http.ResponseWriter) error {
+ session, _ := Store.Get(req, key + SessionName)
+
+ session.Values[key] = value
+
+ return session.Save(req, res)
+}
+
+func getFromSession(key string, req *http.Request) (string, error) {
+ session, _ := Store.Get(req, key + SessionName)
+
+ value := session.Values[key]
+ if value == nil {
+ return "", errors.New("could not find a matching session for this request")
+ }
+
+ return value.(string), nil
+} \ No newline at end of file
diff --git a/vendor/github.com/markbates/goth/provider.go b/vendor/github.com/markbates/goth/provider.go
new file mode 100644
index 0000000000..58d0d60bbf
--- /dev/null
+++ b/vendor/github.com/markbates/goth/provider.go
@@ -0,0 +1,75 @@
+package goth
+
+import (
+ "fmt"
+ "net/http"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+)
+
+// Provider needs to be implemented for each 3rd party authentication provider
+// e.g. Facebook, Twitter, etc...
+type Provider interface {
+ Name() string
+ SetName(name string)
+ BeginAuth(state string) (Session, error)
+ UnmarshalSession(string) (Session, error)
+ FetchUser(Session) (User, error)
+ Debug(bool)
+ RefreshToken(refreshToken string) (*oauth2.Token, error) //Get new access token based on the refresh token
+ RefreshTokenAvailable() bool //Refresh token is provided by auth provider or not
+}
+
+const NoAuthUrlErrorMessage = "an AuthURL has not been set"
+
+// Providers is list of known/available providers.
+type Providers map[string]Provider
+
+var providers = Providers{}
+
+// UseProviders adds a list of available providers for use with Goth.
+// Can be called multiple times. If you pass the same provider more
+// than once, the last will be used.
+func UseProviders(viders ...Provider) {
+ for _, provider := range viders {
+ providers[provider.Name()] = provider
+ }
+}
+
+// GetProviders returns a list of all the providers currently in use.
+func GetProviders() Providers {
+ return providers
+}
+
+// GetProvider returns a previously created provider. If Goth has not
+// been told to use the named provider it will return an error.
+func GetProvider(name string) (Provider, error) {
+ provider := providers[name]
+ if provider == nil {
+ return nil, fmt.Errorf("no provider for %s exists", name)
+ }
+ return provider, nil
+}
+
+// ClearProviders will remove all providers currently in use.
+// This is useful, mostly, for testing purposes.
+func ClearProviders() {
+ providers = Providers{}
+}
+
+// ContextForClient provides a context for use with oauth2.
+func ContextForClient(h *http.Client) context.Context {
+ if h == nil {
+ return oauth2.NoContext
+ }
+ return context.WithValue(oauth2.NoContext, oauth2.HTTPClient, h)
+}
+
+// HTTPClientWithFallBack to be used in all fetch operations.
+func HTTPClientWithFallBack(h *http.Client) *http.Client {
+ if h != nil {
+ return h
+ }
+ return http.DefaultClient
+}
diff --git a/vendor/github.com/markbates/goth/providers/github/github.go b/vendor/github.com/markbates/goth/providers/github/github.go
new file mode 100644
index 0000000000..866150e63a
--- /dev/null
+++ b/vendor/github.com/markbates/goth/providers/github/github.go
@@ -0,0 +1,224 @@
+// Package github implements the OAuth2 protocol for authenticating users through Github.
+// This package can be used as a reference implementation of an OAuth2 provider for Goth.
+package github
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+
+ "github.com/markbates/goth"
+ "golang.org/x/oauth2"
+)
+
+// These vars define the Authentication, Token, and API URLS for GitHub. If
+// using GitHub enterprise you should change these values before calling New.
+//
+// Examples:
+// github.AuthURL = "https://github.acme.com/login/oauth/authorize
+// github.TokenURL = "https://github.acme.com/login/oauth/access_token
+// github.ProfileURL = "https://github.acme.com/api/v3/user
+// github.EmailURL = "https://github.acme.com/api/v3/user/emails
+var (
+ AuthURL = "https://github.com/login/oauth/authorize"
+ TokenURL = "https://github.com/login/oauth/access_token"
+ ProfileURL = "https://api.github.com/user"
+ EmailURL = "https://api.github.com/user/emails"
+)
+
+// New creates a new Github provider, and sets up important connection details.
+// You should always call `github.New` to get a new Provider. Never try to create
+// one manually.
+func New(clientKey, secret, callbackURL string, scopes ...string) *Provider {
+ p := &Provider{
+ ClientKey: clientKey,
+ Secret: secret,
+ CallbackURL: callbackURL,
+ providerName: "github",
+ }
+ p.config = newConfig(p, scopes)
+ return p
+}
+
+// Provider is the implementation of `goth.Provider` for accessing Github.
+type Provider struct {
+ ClientKey string
+ Secret string
+ CallbackURL string
+ HTTPClient *http.Client
+ config *oauth2.Config
+ providerName string
+}
+
+// Name is the name used to retrieve this provider later.
+func (p *Provider) Name() string {
+ return p.providerName
+}
+
+// SetName is to update the name of the provider (needed in case of multiple providers of 1 type)
+func (p *Provider) SetName(name string) {
+ p.providerName = name
+}
+
+func (p *Provider) Client() *http.Client {
+ return goth.HTTPClientWithFallBack(p.HTTPClient)
+}
+
+// Debug is a no-op for the github package.
+func (p *Provider) Debug(debug bool) {}
+
+// BeginAuth asks Github for an authentication end-point.
+func (p *Provider) BeginAuth(state string) (goth.Session, error) {
+ url := p.config.AuthCodeURL(state)
+ session := &Session{
+ AuthURL: url,
+ }
+ return session, nil
+}
+
+// FetchUser will go to Github and access basic information about the user.
+func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
+ sess := session.(*Session)
+ user := goth.User{
+ AccessToken: sess.AccessToken,
+ Provider: p.Name(),
+ }
+
+ if user.AccessToken == "" {
+ // data is not yet retrieved since accessToken is still empty
+ return user, fmt.Errorf("%s cannot get user information without accessToken", p.providerName)
+ }
+
+ response, err := p.Client().Get(ProfileURL + "?access_token=" + url.QueryEscape(sess.AccessToken))
+ if err != nil {
+ return user, err
+ }
+ defer response.Body.Close()
+
+ if response.StatusCode != http.StatusOK {
+ return user, fmt.Errorf("GitHub API responded with a %d trying to fetch user information", response.StatusCode)
+ }
+
+ bits, err := ioutil.ReadAll(response.Body)
+ if err != nil {
+ return user, err
+ }
+
+ err = json.NewDecoder(bytes.NewReader(bits)).Decode(&user.RawData)
+ if err != nil {
+ return user, err
+ }
+
+ err = userFromReader(bytes.NewReader(bits), &user)
+ if err != nil {
+ return user, err
+ }
+
+ if user.Email == "" {
+ for _, scope := range p.config.Scopes {
+ if strings.TrimSpace(scope) == "user" || strings.TrimSpace(scope) == "user:email" {
+ user.Email, err = getPrivateMail(p, sess)
+ if err != nil {
+ return user, err
+ }
+ break
+ }
+ }
+ }
+ return user, err
+}
+
+func userFromReader(reader io.Reader, user *goth.User) error {
+ u := struct {
+ ID int `json:"id"`
+ Email string `json:"email"`
+ Bio string `json:"bio"`
+ Name string `json:"name"`
+ Login string `json:"login"`
+ Picture string `json:"avatar_url"`
+ Location string `json:"location"`
+ }{}
+
+ err := json.NewDecoder(reader).Decode(&u)
+ if err != nil {
+ return err
+ }
+
+ user.Name = u.Name
+ user.NickName = u.Login
+ user.Email = u.Email
+ user.Description = u.Bio
+ user.AvatarURL = u.Picture
+ user.UserID = strconv.Itoa(u.ID)
+ user.Location = u.Location
+
+ return err
+}
+
+func getPrivateMail(p *Provider, sess *Session) (email string, err error) {
+ response, err := p.Client().Get(EmailURL + "?access_token=" + url.QueryEscape(sess.AccessToken))
+ if err != nil {
+ if response != nil {
+ response.Body.Close()
+ }
+ return email, err
+ }
+ defer response.Body.Close()
+
+ if response.StatusCode != http.StatusOK {
+ return email, fmt.Errorf("GitHub API responded with a %d trying to fetch user email", response.StatusCode)
+ }
+
+ var mailList = []struct {
+ Email string `json:"email"`
+ Primary bool `json:"primary"`
+ Verified bool `json:"verified"`
+ }{}
+ err = json.NewDecoder(response.Body).Decode(&mailList)
+ if err != nil {
+ return email, err
+ }
+ for _, v := range mailList {
+ if v.Primary && v.Verified {
+ return v.Email, nil
+ }
+ }
+ // can't get primary email - shouldn't be possible
+ return
+}
+
+func newConfig(provider *Provider, scopes []string) *oauth2.Config {
+ c := &oauth2.Config{
+ ClientID: provider.ClientKey,
+ ClientSecret: provider.Secret,
+ RedirectURL: provider.CallbackURL,
+ Endpoint: oauth2.Endpoint{
+ AuthURL: AuthURL,
+ TokenURL: TokenURL,
+ },
+ Scopes: []string{},
+ }
+
+ for _, scope := range scopes {
+ c.Scopes = append(c.Scopes, scope)
+ }
+
+ return c
+}
+
+//RefreshToken refresh token is not provided by github
+func (p *Provider) RefreshToken(refreshToken string) (*oauth2.Token, error) {
+ return nil, errors.New("Refresh token is not provided by github")
+}
+
+//RefreshTokenAvailable refresh token is not provided by github
+func (p *Provider) RefreshTokenAvailable() bool {
+ return false
+}
diff --git a/vendor/github.com/markbates/goth/providers/github/session.go b/vendor/github.com/markbates/goth/providers/github/session.go
new file mode 100644
index 0000000000..f473a526e5
--- /dev/null
+++ b/vendor/github.com/markbates/goth/providers/github/session.go
@@ -0,0 +1,56 @@
+package github
+
+import (
+ "encoding/json"
+ "errors"
+ "strings"
+
+ "github.com/markbates/goth"
+)
+
+// Session stores data during the auth process with Github.
+type Session struct {
+ AuthURL string
+ AccessToken string
+}
+
+// GetAuthURL will return the URL set by calling the `BeginAuth` function on the Github provider.
+func (s Session) GetAuthURL() (string, error) {
+ if s.AuthURL == "" {
+ return "", errors.New(goth.NoAuthUrlErrorMessage)
+ }
+ return s.AuthURL, nil
+}
+
+// Authorize the session with Github and return the access token to be stored for future use.
+func (s *Session) Authorize(provider goth.Provider, params goth.Params) (string, error) {
+ p := provider.(*Provider)
+ token, err := p.config.Exchange(goth.ContextForClient(p.Client()), params.Get("code"))
+ if err != nil {
+ return "", err
+ }
+
+ if !token.Valid() {
+ return "", errors.New("Invalid token received from provider")
+ }
+
+ s.AccessToken = token.AccessToken
+ return token.AccessToken, err
+}
+
+// Marshal the session into a string
+func (s Session) Marshal() string {
+ b, _ := json.Marshal(s)
+ return string(b)
+}
+
+func (s Session) String() string {
+ return s.Marshal()
+}
+
+// UnmarshalSession will unmarshal a JSON string into a session.
+func (p *Provider) UnmarshalSession(data string) (goth.Session, error) {
+ sess := &Session{}
+ err := json.NewDecoder(strings.NewReader(data)).Decode(sess)
+ return sess, err
+}
diff --git a/vendor/github.com/markbates/goth/session.go b/vendor/github.com/markbates/goth/session.go
new file mode 100644
index 0000000000..2d40b50bb4
--- /dev/null
+++ b/vendor/github.com/markbates/goth/session.go
@@ -0,0 +1,21 @@
+package goth
+
+// Params is used to pass data to sessions for authorization. An existing
+// implementation, and the one most likely to be used, is `url.Values`.
+type Params interface {
+ Get(string) string
+}
+
+// Session needs to be implemented as part of the provider package.
+// It will be marshaled and persisted between requests to "tie"
+// the start and the end of the authorization process with a
+// 3rd party provider.
+type Session interface {
+ // GetAuthURL returns the URL for the authentication end-point for the provider.
+ GetAuthURL() (string, error)
+ // Marshal generates a string representation of the Session for storing between requests.
+ Marshal() string
+ // Authorize should validate the data from the provider and return an access token
+ // that can be stored for later access to the provider.
+ Authorize(Provider, Params) (string, error)
+}
diff --git a/vendor/github.com/markbates/goth/user.go b/vendor/github.com/markbates/goth/user.go
new file mode 100644
index 0000000000..1d6a419632
--- /dev/null
+++ b/vendor/github.com/markbates/goth/user.go
@@ -0,0 +1,30 @@
+package goth
+
+import (
+ "encoding/gob"
+ "time"
+)
+
+func init() {
+ gob.Register(User{})
+}
+
+// User contains the information common amongst most OAuth and OAuth2 providers.
+// All of the "raw" datafrom the provider can be found in the `RawData` field.
+type User struct {
+ RawData map[string]interface{}
+ Provider string
+ Email string
+ Name string
+ FirstName string
+ LastName string
+ NickName string
+ Description string
+ UserID string
+ AvatarURL string
+ Location string
+ AccessToken string
+ AccessTokenSecret string
+ RefreshToken string
+ ExpiresAt time.Time
+}