summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/markbates/goth/gothic/gothic.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/markbates/goth/gothic/gothic.go')
-rw-r--r--vendor/github.com/markbates/goth/gothic/gothic.go219
1 files changed, 219 insertions, 0 deletions
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