git.iko.soy/typeable/oauth2-proxy
on master help sign in
Integrate Provider into Options and OauthProxy
commitd9a945ebc3a4f5f28d70b7469d212a1c37ad0047 authorMike Bland <michael.bland@gsa.gov> dateMon 30 Mar 2015, 15:48 (12 years ago) parente2931da
4 files changed+56−37
main.go+6 oauthproxy.go+7−31 options.go+31−6 options_test.go+12
main.go+6
@@ -50,6 +50,12 @@ func main() {
5050
5151 flagSet.Bool("request-logging", true, "Log requests to stdout")
5252
53+ flagSet.String("provider", "", "Oauth provider (defaults to Google)")
54+ flagSet.String("login-url", "", "Authentication endpoint")
55+ flagSet.String("redeem-url", "", "Token redemption endpoint")
56+ flagSet.String("profile-url", "", "Profile access endpoint")
57+ flagSet.String("scope", "", "Oauth scope specification")
58+
5359 flagSet.Parse(os.Args[1:])
5460
5561 if *showVersion {
oauthproxy.go+7−31
@@ -15,8 +15,8 @@ import (
1515 "strings"
1616 "time"
1717
18− "github.com/bitly/go-simplejson"
1918 "github.com/bitly/google_auth_proxy/api"
19+ "github.com/bitly/google_auth_proxy/providers"
2020)
2121
2222const pingPath = "/ping"
@@ -34,6 +34,7 @@ type OauthProxy struct {
3434 Validator func(string) bool
3535
3636 redirectUrl *url.URL // the url to receive requests at
37+ provider providers.Provider
3738 oauthRedemptionUrl *url.URL // endpoint to redeem the code
3839 oauthLoginUrl *url.URL // to redirect the user to
3940 oauthScope string
@@ -83,8 +84,6 @@ func setProxyDirector(proxy *httputil.ReverseProxy) {
8384}
8485
8586func NewOauthProxy(opts *Options, validator func(string) bool) *OauthProxy {
86− login, _ := url.Parse("https://accounts.google.com/o/oauth2/auth")
87− redeem, _ := url.Parse("https://accounts.google.com/o/oauth2/token")
8887 serveMux := http.NewServeMux()
8988 for _, u := range opts.proxyUrls {
9089 path := u.Path
@@ -128,9 +127,10 @@ func NewOauthProxy(opts *Options, validator func(string) bool) *OauthProxy {
128127
129128 clientID: opts.ClientID,
130129 clientSecret: opts.ClientSecret,
131− oauthScope: "profile email",
132− oauthRedemptionUrl: redeem,
133− oauthLoginUrl: login,
130+ oauthScope: opts.provider.Data().Scope,
131+ provider: opts.provider,
132+ oauthRedemptionUrl: opts.provider.Data().RedeemUrl,
133+ oauthLoginUrl: opts.provider.Data().LoginUrl,
134134 serveMux: serveMux,
135135 redirectUrl: redirectUrl,
136136 skipAuthRegex: opts.SkipAuthRegex,
@@ -201,23 +201,7 @@ func (p *OauthProxy) redeemCode(host, code string) (string, string, error) {
201201 return "", "", err
202202 }
203203
204− idToken, err := json.Get("id_token").String()
205− if err != nil {
206− return "", "", err
207− }
208−
209− // id_token is a base64 encode ID token payload
210− // https://developers.google.com/accounts/docs/OAuth2Login#obtainuserinfo
211− jwt := strings.Split(idToken, ".")
212− b, err := jwtDecodeSegment(jwt[1])
213− if err != nil {
214− return "", "", err
215− }
216− data, err := simplejson.NewJson(b)
217− if err != nil {
218− return "", "", err
219− }
220− email, err := data.Get("email").String()
204+ email, err := p.provider.GetEmailAddress(json, access_token)
221205 if err != nil {
222206 return "", "", err
223207 }
@@ -225,14 +209,6 @@ func (p *OauthProxy) redeemCode(host, code string) (string, string, error) {
225209 return access_token, email, nil
226210}
227211
228−func jwtDecodeSegment(seg string) ([]byte, error) {
229− if l := len(seg) % 4; l > 0 {
230− seg += strings.Repeat("=", 4-l)
231− }
232−
233− return base64.URLEncoding.DecodeString(seg)
234−}
235−
236212func (p *OauthProxy) ClearCookie(rw http.ResponseWriter, req *http.Request) {
237213 domain := req.Host
238214 if h, _, err := net.SplitHostPort(domain); err == nil {
options.go+31−6
@@ -6,6 +6,8 @@ import (
66 "regexp"
77 "strings"
88 "time"
9+
10+ "github.com/bitly/google_auth_proxy/providers"
911)
1012
1113// Configuration Options that can be set by Command Line Flag, or Config File
@@ -33,12 +35,21 @@ type Options struct {
3335 PassBasicAuth bool `flag:"pass-basic-auth" cfg:"pass_basic_auth"`
3436 PassHostHeader bool `flag:"pass-host-header" cfg:"pass_host_header"`
3537
38+ // These options allow for other providers besides Google, with
39+ // potential overrides.
40+ Provider string `flag:"provider" cfg:"provider"`
41+ LoginUrl string `flag:"login-url" cfg:"login_url"`
42+ RedeemUrl string `flag:"redeem-url" cfg:"redeem_url"`
43+ ProfileUrl string `flag:"profile-url" cfg:"profile_url"`
44+ Scope string `flag:"scope" cfg:"scope"`
45+
3646 RequestLogging bool `flag:"request-logging" cfg:"request_logging"`
3747
3848 // internal values that are set after config validation
3949 redirectUrl *url.URL
4050 proxyUrls []*url.URL
4151 CompiledRegex []*regexp.Regexp
52+ provider providers.Provider
4253}
4354
4455func NewOptions() *Options {
@@ -55,6 +66,15 @@ func NewOptions() *Options {
5566 }
5667}
5768
69+func parseUrl(to_parse string, urltype string, msgs []string) (*url.URL, []string) {
70+ parsed, err := url.Parse(to_parse)
71+ if err != nil {
72+ return nil, append(msgs, fmt.Sprintf(
73+ "error parsing %s-url=%q %s", urltype, to_parse, err))
74+ }
75+ return parsed, msgs
76+}
77+
5878func (o *Options) Validate() error {
5979 msgs := make([]string, 0)
6080 if len(o.Upstreams) < 1 {
@@ -70,12 +90,7 @@ func (o *Options) Validate() error {
7090 msgs = append(msgs, "missing setting: client-secret")
7191 }
7292
73− redirectUrl, err := url.Parse(o.RedirectUrl)
74− if err != nil {
75− msgs = append(msgs, fmt.Sprintf(
76− "error parsing redirect-url=%q %s", o.RedirectUrl, err))
77− }
78− o.redirectUrl = redirectUrl
93+ o.redirectUrl, msgs = parseUrl(o.RedirectUrl, "redirect", msgs)
7994
8095 for _, u := range o.Upstreams {
8196 upstreamUrl, err := url.Parse(u)
@@ -98,6 +113,7 @@ func (o *Options) Validate() error {
98113 }
99114 o.CompiledRegex = append(o.CompiledRegex, CompiledRegex)
100115 }
116+ msgs = parseProviderInfo(o, msgs)
101117
102118 if len(msgs) != 0 {
103119 return fmt.Errorf("Invalid configuration:\n %s",
@@ -105,3 +121,12 @@ func (o *Options) Validate() error {
105121 }
106122 return nil
107123}
124+
125+func parseProviderInfo(o *Options, msgs []string) []string {
126+ p := &providers.ProviderData{Scope: o.Scope}
127+ p.LoginUrl, msgs = parseUrl(o.LoginUrl, "login", msgs)
128+ p.RedeemUrl, msgs = parseUrl(o.RedeemUrl, "redeem", msgs)
129+ p.ProfileUrl, msgs = parseUrl(o.ProfileUrl, "profile", msgs)
130+ o.provider = providers.New(o.Provider, p)
131+ return msgs
132+}
options_test.go+12
@@ -90,3 +90,15 @@ func TestCompiledRegexError(t *testing.T) {
9090 "unexpected ): `barquux)`"})
9191 assert.Equal(t, expected, err.Error())
9292}
93+
94+func TestDefaultProviderApiSettings(t *testing.T) {
95+ o := testOptions()
96+ assert.Equal(t, nil, o.Validate())
97+ p := o.provider.Data()
98+ assert.Equal(t, "https://accounts.google.com/o/oauth2/auth",
99+ p.LoginUrl.String())
100+ assert.Equal(t, "https://accounts.google.com/o/oauth2/token",
101+ p.RedeemUrl.String())
102+ assert.Equal(t, "", p.ProfileUrl.String())
103+ assert.Equal(t, "profile email", p.Scope)
104+}