150 lines
4.3 KiB
Go
150 lines
4.3 KiB
Go
// Package provider implements all oauth2, oauth1 as well as custom and direct providers
|
|
package provider
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"golang.org/x/oauth2/facebook"
|
|
"golang.org/x/oauth2/github"
|
|
"golang.org/x/oauth2/google"
|
|
"golang.org/x/oauth2/yandex"
|
|
|
|
"github.com/dghubble/oauth1"
|
|
"github.com/dghubble/oauth1/twitter"
|
|
|
|
"github.com/go-pkgz/auth/token"
|
|
)
|
|
|
|
// NewGoogle makes google oauth2 provider
|
|
func NewGoogle(p Params) Oauth2Handler {
|
|
return initOauth2Handler(p, Oauth2Handler{
|
|
name: "google",
|
|
endpoint: google.Endpoint,
|
|
scopes: []string{"https://www.googleapis.com/auth/userinfo.profile"},
|
|
infoURL: "https://www.googleapis.com/oauth2/v3/userinfo",
|
|
mapUser: func(data UserData, _ []byte) token.User {
|
|
userInfo := token.User{
|
|
// encode email with provider name to avoid collision if same id returned by other provider
|
|
ID: "google_" + token.HashID(sha1.New(), data.Value("sub")),
|
|
Name: data.Value("name"),
|
|
Picture: data.Value("picture"),
|
|
}
|
|
if userInfo.Name == "" {
|
|
userInfo.Name = "noname_" + userInfo.ID[8:12]
|
|
}
|
|
return userInfo
|
|
},
|
|
})
|
|
}
|
|
|
|
// NewGithub makes github oauth2 provider
|
|
func NewGithub(p Params) Oauth2Handler {
|
|
return initOauth2Handler(p, Oauth2Handler{
|
|
name: "github",
|
|
endpoint: github.Endpoint,
|
|
scopes: []string{},
|
|
infoURL: "https://api.github.com/user",
|
|
mapUser: func(data UserData, _ []byte) token.User {
|
|
userInfo := token.User{
|
|
ID: "github_" + token.HashID(sha1.New(), data.Value("login")),
|
|
Name: data.Value("name"),
|
|
Picture: data.Value("avatar_url"),
|
|
}
|
|
// github may have no user name, use login in this case
|
|
if userInfo.Name == "" {
|
|
userInfo.Name = data.Value("login")
|
|
}
|
|
return userInfo
|
|
},
|
|
})
|
|
}
|
|
|
|
// NewFacebook makes facebook oauth2 provider
|
|
func NewFacebook(p Params) Oauth2Handler {
|
|
|
|
// response format for fb /me call
|
|
type uinfo struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Picture struct {
|
|
Data struct {
|
|
URL string `json:"url"`
|
|
} `json:"data"`
|
|
} `json:"picture"`
|
|
}
|
|
|
|
return initOauth2Handler(p, Oauth2Handler{
|
|
name: "facebook",
|
|
endpoint: facebook.Endpoint,
|
|
scopes: []string{"public_profile"},
|
|
infoURL: "https://graph.facebook.com/me?fields=id,name,picture",
|
|
mapUser: func(data UserData, bdata []byte) token.User {
|
|
userInfo := token.User{
|
|
ID: "facebook_" + token.HashID(sha1.New(), data.Value("id")),
|
|
Name: data.Value("name"),
|
|
}
|
|
if userInfo.Name == "" {
|
|
userInfo.Name = userInfo.ID[0:16]
|
|
}
|
|
|
|
uinfoJSON := uinfo{}
|
|
if err := json.Unmarshal(bdata, &uinfoJSON); err == nil {
|
|
userInfo.Picture = uinfoJSON.Picture.Data.URL
|
|
}
|
|
return userInfo
|
|
},
|
|
})
|
|
}
|
|
|
|
// NewYandex makes yandex oauth2 provider
|
|
func NewYandex(p Params) Oauth2Handler {
|
|
return initOauth2Handler(p, Oauth2Handler{
|
|
name: "yandex",
|
|
endpoint: yandex.Endpoint,
|
|
scopes: []string{},
|
|
// See https://tech.yandex.com/passport/doc/dg/reference/response-docpage/
|
|
infoURL: "https://login.yandex.ru/info?format=json",
|
|
mapUser: func(data UserData, _ []byte) token.User {
|
|
userInfo := token.User{
|
|
ID: "yandex_" + token.HashID(sha1.New(), data.Value("id")),
|
|
Name: data.Value("display_name"), // using Display Name by default
|
|
}
|
|
if userInfo.Name == "" {
|
|
userInfo.Name = data.Value("real_name") // using Real Name (== full name) if Display Name is empty
|
|
}
|
|
if userInfo.Name == "" {
|
|
userInfo.Name = data.Value("login") // otherwise using login
|
|
}
|
|
|
|
if data.Value("default_avatar_id") != "" {
|
|
userInfo.Picture = fmt.Sprintf("https://avatars.yandex.net/get-yapic/%s/islands-200", data.Value("default_avatar_id"))
|
|
}
|
|
return userInfo
|
|
},
|
|
})
|
|
}
|
|
|
|
// NewTwitter makes twitter oauth2 provider
|
|
func NewTwitter(p Params) Oauth1Handler {
|
|
return initOauth1Handler(p, Oauth1Handler{
|
|
name: "twitter",
|
|
conf: oauth1.Config{
|
|
Endpoint: twitter.AuthorizeEndpoint,
|
|
},
|
|
infoURL: "https://api.twitter.com/1.1/account/verify_credentials.json",
|
|
mapUser: func(data UserData, _ []byte) token.User {
|
|
userInfo := token.User{
|
|
ID: "twitter_" + token.HashID(sha1.New(), data.Value("id_str")),
|
|
Name: data.Value("screen_name"),
|
|
Picture: data.Value("profile_image_url_https"),
|
|
}
|
|
if userInfo.Name == "" {
|
|
userInfo.Name = data.Value("name")
|
|
}
|
|
return userInfo
|
|
},
|
|
})
|
|
}
|