mirror of https://github.com/dexidp/dex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
3.5 KiB
145 lines
3.5 KiB
package connector |
|
|
|
import ( |
|
"encoding/json" |
|
"fmt" |
|
"html/template" |
|
"net/http" |
|
"net/url" |
|
"path" |
|
"strconv" |
|
|
|
chttp "github.com/coreos/go-oidc/http" |
|
"github.com/coreos/go-oidc/oauth2" |
|
"github.com/coreos/go-oidc/oidc" |
|
) |
|
|
|
const ( |
|
GitHubConnectorType = "github" |
|
githubAuthURL = "https://github.com/login/oauth/authorize" |
|
githubTokenURL = "https://github.com/login/oauth/access_token" |
|
githubAPIUserURL = "https://api.github.com/user" |
|
) |
|
|
|
func init() { |
|
RegisterConnectorConfigType(GitHubConnectorType, func() ConnectorConfig { return &GitHubConnectorConfig{} }) |
|
} |
|
|
|
type GitHubConnectorConfig struct { |
|
ID string `json:"id"` |
|
ClientID string `json:"clientID"` |
|
ClientSecret string `json:"clientSecret"` |
|
} |
|
|
|
func (cfg *GitHubConnectorConfig) ConnectorID() string { |
|
return cfg.ID |
|
} |
|
|
|
func (cfg *GitHubConnectorConfig) ConnectorType() string { |
|
return GitHubConnectorType |
|
} |
|
|
|
func (cfg *GitHubConnectorConfig) Connector(ns url.URL, lf oidc.LoginFunc, tpls *template.Template) (Connector, error) { |
|
ns.Path = path.Join(ns.Path, httpPathCallback) |
|
oauth2Conn, err := newGitHubConnector(cfg.ClientID, cfg.ClientSecret, ns.String()) |
|
if err != nil { |
|
return nil, err |
|
} |
|
return &OAuth2Connector{ |
|
id: cfg.ID, |
|
loginFunc: lf, |
|
cbURL: ns, |
|
conn: oauth2Conn, |
|
}, nil |
|
} |
|
|
|
type githubOAuth2Connector struct { |
|
clientID string |
|
clientSecret string |
|
client *oauth2.Client |
|
} |
|
|
|
func newGitHubConnector(clientID, clientSecret, cbURL string) (oauth2Connector, error) { |
|
config := oauth2.Config{ |
|
Credentials: oauth2.ClientCredentials{ID: clientID, Secret: clientSecret}, |
|
AuthURL: githubAuthURL, |
|
TokenURL: githubTokenURL, |
|
Scope: []string{"user:email"}, |
|
AuthMethod: oauth2.AuthMethodClientSecretPost, |
|
RedirectURL: cbURL, |
|
} |
|
|
|
cli, err := oauth2.NewClient(http.DefaultClient, config) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
return &githubOAuth2Connector{ |
|
clientID: clientID, |
|
clientSecret: clientSecret, |
|
client: cli, |
|
}, nil |
|
} |
|
|
|
// standard error form returned by github |
|
type githubError struct { |
|
Message string `json:"message"` |
|
} |
|
|
|
func (err githubError) Error() string { |
|
return fmt.Sprintf("github: %s", err.Message) |
|
} |
|
|
|
func (c *githubOAuth2Connector) Client() *oauth2.Client { |
|
return c.client |
|
} |
|
|
|
func (c *githubOAuth2Connector) Identity(cli chttp.Client) (oidc.Identity, error) { |
|
req, err := http.NewRequest("GET", githubAPIUserURL, nil) |
|
if err != nil { |
|
return oidc.Identity{}, err |
|
} |
|
resp, err := cli.Do(req) |
|
if err != nil { |
|
return oidc.Identity{}, fmt.Errorf("get: %v", err) |
|
} |
|
defer resp.Body.Close() |
|
switch { |
|
case resp.StatusCode >= 400 && resp.StatusCode < 600: |
|
// attempt to decode error from github |
|
var authErr githubError |
|
if err := json.NewDecoder(resp.Body).Decode(&authErr); err != nil { |
|
return oidc.Identity{}, oauth2.NewError(oauth2.ErrorAccessDenied) |
|
} |
|
return oidc.Identity{}, authErr |
|
case resp.StatusCode == http.StatusOK: |
|
default: |
|
return oidc.Identity{}, fmt.Errorf("unexpected status from providor %s", resp.Status) |
|
} |
|
var user struct { |
|
Login string `json:"login"` |
|
ID int64 `json:"id"` |
|
Email string `json:"email"` |
|
Name string `json:"name"` |
|
} |
|
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil { |
|
return oidc.Identity{}, fmt.Errorf("getting user info: %v", err) |
|
} |
|
name := user.Name |
|
if name == "" { |
|
name = user.Login |
|
} |
|
return oidc.Identity{ |
|
ID: strconv.FormatInt(user.ID, 10), |
|
Name: name, |
|
Email: user.Email, |
|
}, nil |
|
} |
|
|
|
func (c *githubOAuth2Connector) Healthy() error { |
|
return nil |
|
} |
|
|
|
func (c *githubOAuth2Connector) TrustedEmailProvider() bool { |
|
return false |
|
}
|
|
|