-
Notifications
You must be signed in to change notification settings - Fork 327
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
159 additions
and
147 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
package cfg | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"net/http" | ||
"strings" | ||
|
||
"golang.org/x/oauth2" | ||
"golang.org/x/oauth2/github" | ||
"golang.org/x/oauth2/google" | ||
) | ||
|
||
type oidcDiscoveryJSON struct { | ||
Issuer string `json:"issuer"` | ||
AuthURL string `json:"authorization_endpoint"` | ||
TokenURL string `json:"token_endpoint"` | ||
UserInfoURL string `json:"userinfo_endpoint"` | ||
ScopesSupported []string `json:"scopes_supported"` | ||
} | ||
|
||
func configureOAuth() { | ||
// OAuth defaults and client configuration | ||
if err := UnmarshalKey("oauth", &GenOAuth); err != nil { | ||
log.Fatalf("error configuring oauth %s", err.Error()) | ||
} | ||
if GenOAuth.Provider == Providers.Google { | ||
setDefaultsGoogle() | ||
// setDefaultsGoogle also configures the OAuthClient | ||
} else if GenOAuth.Provider == Providers.GitHub { | ||
setDefaultsGitHub() | ||
configureOAuthClient() | ||
} else if GenOAuth.Provider == Providers.ADFS { | ||
setDefaultsADFS() | ||
configureOAuthClient() | ||
} else if GenOAuth.Provider == Providers.OIDC && GenOAuth.ProviderURL != "" { | ||
if err := setOAuthDefaultsOIDCDiscovery(); err != nil { | ||
log.Errorf("error setting endpoints from OIDC Discovery: %s", err.Error()) | ||
} | ||
} else { | ||
configureOAuthClient() | ||
} | ||
|
||
} | ||
|
||
// retrieve JSON from provider's /.well-known/openid-configuration and configure endpoints | ||
func setOAuthDefaultsOIDCDiscovery() error { | ||
// func NewProvider(ctx context.Context, issuer string) (*Provider, error) { | ||
wellKnownURL := strings.TrimSuffix(GenOAuth.ProviderURL, "/") + "/.well-known/openid-configuration" | ||
log.Infof("configuring oauth enpoints via OIDC Discovery from %s", wellKnownURL) | ||
req, err := http.NewRequest("GET", wellKnownURL, nil) | ||
if err != nil { | ||
return err | ||
} | ||
resp, err := http.DefaultClient.Do(req) | ||
if err != nil { | ||
return err | ||
} | ||
defer resp.Body.Close() | ||
|
||
body, err := ioutil.ReadAll(resp.Body) | ||
if err != nil { | ||
return fmt.Errorf("oidc: unable to read response body: %v", err) | ||
} | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
return fmt.Errorf("%s: %s", resp.Status, body) | ||
} | ||
|
||
var oidcD oidcDiscoveryJSON | ||
err = json.Unmarshal(body, &oidcD) | ||
if err != nil { | ||
return fmt.Errorf("oidc: couldn't read json from provider: %v", err) | ||
} | ||
|
||
if GenOAuth.ProviderURL != oidcD.Issuer { | ||
return fmt.Errorf("oidc: issuers did not match, wanted: %q got: %q", GenOAuth.ProviderURL, oidcD.Issuer) | ||
} | ||
|
||
// SUCCESS!! | ||
// set the retrieved items | ||
|
||
GenOAuth.AuthURL = oidcD.AuthURL | ||
GenOAuth.TokenURL = oidcD.TokenURL | ||
GenOAuth.UserInfoURL = oidcD.UserInfoURL | ||
|
||
if len(oidcD.ScopesSupported) > 0 { | ||
GenOAuth.Scopes = oidcD.ScopesSupported | ||
} else { | ||
GenOAuth.Scopes = []string{"openid"} | ||
} | ||
|
||
log.Debugf("set oauth.AuthURL %s", GenOAuth.AuthURL) | ||
log.Debugf("set oauth.TokenURL %s", GenOAuth.TokenURL) | ||
log.Debugf("set oauth.UserInfoURL %s", GenOAuth.UserInfoURL) | ||
log.Debugf("set oauth.Scopes %s", GenOAuth.Scopes) | ||
|
||
return nil | ||
} | ||
|
||
func setDefaultsGoogle() { | ||
log.Info("configuring Google OAuth") | ||
GenOAuth.UserInfoURL = "https://www.googleapis.com/oauth2/v3/userinfo" | ||
OAuthClient = &oauth2.Config{ | ||
ClientID: GenOAuth.ClientID, | ||
ClientSecret: GenOAuth.ClientSecret, | ||
Scopes: []string{ | ||
// You have to select a scope from | ||
// https://developers.google.com/identity/protocols/googlescopes#google_sign-in | ||
"https://www.googleapis.com/auth/userinfo.email", | ||
}, | ||
Endpoint: google.Endpoint, | ||
} | ||
if GenOAuth.PreferredDomain != "" { | ||
log.Infof("setting Google OAuth preferred login domain param 'hd' to %s", GenOAuth.PreferredDomain) | ||
OAuthopts = oauth2.SetAuthURLParam("hd", GenOAuth.PreferredDomain) | ||
} | ||
} | ||
|
||
func setDefaultsADFS() { | ||
log.Info("configuring ADFS OAuth") | ||
OAuthopts = oauth2.SetAuthURLParam("resource", GenOAuth.RedirectURL) // Needed or all claims won't be included | ||
} | ||
|
||
func setDefaultsGitHub() { | ||
// log.Info("configuring GitHub OAuth") | ||
if GenOAuth.AuthURL == "" { | ||
GenOAuth.AuthURL = github.Endpoint.AuthURL | ||
} | ||
if GenOAuth.TokenURL == "" { | ||
GenOAuth.TokenURL = github.Endpoint.TokenURL | ||
} | ||
if GenOAuth.UserInfoURL == "" { | ||
GenOAuth.UserInfoURL = "https://api.github.com/user?access_token=" | ||
} | ||
if len(GenOAuth.Scopes) == 0 { | ||
// https://github.com/vouch/vouch-proxy/issues/63 | ||
// https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/ | ||
GenOAuth.Scopes = []string{"read:user"} | ||
} | ||
} | ||
|
||
func configureOAuthClient() { | ||
log.Infof("configuring %s OAuth with Endpoint %s", GenOAuth.Provider, GenOAuth.AuthURL) | ||
OAuthClient = &oauth2.Config{ | ||
ClientID: GenOAuth.ClientID, | ||
ClientSecret: GenOAuth.ClientSecret, | ||
Endpoint: oauth2.Endpoint{ | ||
AuthURL: GenOAuth.AuthURL, | ||
TokenURL: GenOAuth.TokenURL, | ||
}, | ||
RedirectURL: GenOAuth.RedirectURL, | ||
Scopes: GenOAuth.Scopes, | ||
} | ||
} |
7a715e7
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a PR for this to go into master?
7a715e7
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is not.
I'd prefer to use https://github.com/coreos/go-oidc if possible, including verification of the provider token.
There's some glue code needed and management of some other settings including
GenOAuth.UserInfoURL
but it should be fairly straight forward.Would you be interested in working on a PR for that?
7a715e7
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can give it a fork, review the code and see what I might be able to do. Go is not my first language but I dabbled a bit quite a few years ago. Whats the best way to chat with you about Vouch and the direction of the project?
7a715e7
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jessecooper that would be pretty sweet, would love the help.
The best way to chat would be in the freenode IRC channel
#vouch
I'm happy to set a time with you, with a preference for PDT(-07:00) working hours.
For consistency, lets keep any further conversation here in github within issue #41
Thanks much!