Skip to content

Commit

Permalink
connector(oidc): support the implicit flow
Browse files Browse the repository at this point in the history
Signed-off-by: Cole Mickens <[email protected]>
  • Loading branch information
colemickens committed Feb 16, 2019
1 parent 8b378ba commit 9ff5eb1
Show file tree
Hide file tree
Showing 15 changed files with 176 additions and 70 deletions.
8 changes: 4 additions & 4 deletions connector/bitbucketcloud/bitbucketcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,12 @@ func (b *bitbucketConnector) oauth2Config(scopes connector.Scopes) *oauth2.Confi
}
}

func (b *bitbucketConnector) LoginURL(scopes connector.Scopes, callbackURL, state string) (string, error) {
func (b *bitbucketConnector) LoginURL(scopes connector.Scopes, callbackURL, state string) (string, []byte, error) {
if b.redirectURI != callbackURL {
return "", fmt.Errorf("expected callback URL %q did not match the URL in the config %q", callbackURL, b.redirectURI)
return "", nil, fmt.Errorf("expected callback URL %q did not match the URL in the config %q", callbackURL, b.redirectURI)
}

return b.oauth2Config(scopes).AuthCodeURL(state), nil
return b.oauth2Config(scopes).AuthCodeURL(state), nil, nil
}

type oauth2Error struct {
Expand All @@ -125,7 +125,7 @@ func (e *oauth2Error) Error() string {
return e.error + ": " + e.errorDescription
}

func (b *bitbucketConnector) HandleCallback(s connector.Scopes, r *http.Request) (identity connector.Identity, err error) {
func (b *bitbucketConnector) HandleCallback(s connector.Scopes, r *http.Request, connDataBytes []byte) (identity connector.Identity, err error) {
q := r.URL.Query()
if errType := q.Get("error"); errType != "" {
return identity, &oauth2Error{errType, q.Get("error_description")}
Expand Down
2 changes: 1 addition & 1 deletion connector/bitbucketcloud/bitbucketcloud_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func TestUsernameIncludedInFederatedIdentity(t *testing.T) {
expectNil(t, err)

bitbucketConnector := bitbucketConnector{apiURL: s.URL, hostName: hostURL.Host, httpClient: newClient()}
identity, err := bitbucketConnector.HandleCallback(connector.Scopes{}, req)
identity, err := bitbucketConnector.HandleCallback(connector.Scopes{}, req, nil)

expectNil(t, err)
expectEquals(t, identity.Username, "some-login")
Expand Down
4 changes: 2 additions & 2 deletions connector/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ type CallbackConnector interface {
// requested if one has already been issues. There's no good general answer
// for these kind of restrictions, and may require this package to become more
// aware of the global set of user/connector interactions.
LoginURL(s Scopes, callbackURL, state string) (string, error)
LoginURL(s Scopes, callbackURL, state string) (string, []byte, error)

// Handle the callback to the server and return an identity.
HandleCallback(s Scopes, r *http.Request) (identity Identity, err error)
HandleCallback(s Scopes, r *http.Request, data []byte) (identity Identity, err error)
}

// SAMLConnector represents SAML connectors which implement the HTTP POST binding.
Expand Down
8 changes: 4 additions & 4 deletions connector/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,12 @@ func (c *githubConnector) oauth2Config(scopes connector.Scopes) *oauth2.Config {
}
}

func (c *githubConnector) LoginURL(scopes connector.Scopes, callbackURL, state string) (string, error) {
func (c *githubConnector) LoginURL(scopes connector.Scopes, callbackURL, state string) (string, []byte, error) {
if c.redirectURI != callbackURL {
return "", fmt.Errorf("expected callback URL %q did not match the URL in the config %q", callbackURL, c.redirectURI)
return "", nil, fmt.Errorf("expected callback URL %q did not match the URL in the config %q", callbackURL, c.redirectURI)
}

return c.oauth2Config(scopes).AuthCodeURL(state), nil
return c.oauth2Config(scopes).AuthCodeURL(state), nil, nil
}

type oauth2Error struct {
Expand Down Expand Up @@ -234,7 +234,7 @@ func newHTTPClient(rootCA string) (*http.Client, error) {
}, nil
}

func (c *githubConnector) HandleCallback(s connector.Scopes, r *http.Request) (identity connector.Identity, err error) {
func (c *githubConnector) HandleCallback(s connector.Scopes, r *http.Request, connDataBytes []byte) (identity connector.Identity, err error) {
q := r.URL.Query()
if errType := q.Get("error"); errType != "" {
return identity, &oauth2Error{errType, q.Get("error_description")}
Expand Down
6 changes: 3 additions & 3 deletions connector/github/github_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,15 +151,15 @@ func TestUsernameIncludedInFederatedIdentity(t *testing.T) {
expectNil(t, err)

c := githubConnector{apiURL: s.URL, hostName: hostURL.Host, httpClient: newClient()}
identity, err := c.HandleCallback(connector.Scopes{Groups: true}, req)
identity, err := c.HandleCallback(connector.Scopes{Groups: true}, req, nil)

expectNil(t, err)
expectEquals(t, identity.Username, "some-login")
expectEquals(t, identity.UserID, "12345678")
expectEquals(t, 0, len(identity.Groups))

c = githubConnector{apiURL: s.URL, hostName: hostURL.Host, httpClient: newClient(), loadAllGroups: true}
identity, err = c.HandleCallback(connector.Scopes{Groups: true}, req)
identity, err = c.HandleCallback(connector.Scopes{Groups: true}, req, nil)

expectNil(t, err)
expectEquals(t, identity.Username, "some-login")
Expand Down Expand Up @@ -193,7 +193,7 @@ func TestLoginUsedAsIDWhenConfigured(t *testing.T) {
expectNil(t, err)

c := githubConnector{apiURL: s.URL, hostName: hostURL.Host, httpClient: newClient(), useLoginAsID: true}
identity, err := c.HandleCallback(connector.Scopes{Groups: true}, req)
identity, err := c.HandleCallback(connector.Scopes{Groups: true}, req, nil)

expectNil(t, err)
expectEquals(t, identity.UserID, "some-login")
Expand Down
8 changes: 4 additions & 4 deletions connector/gitlab/gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ func (c *gitlabConnector) oauth2Config(scopes connector.Scopes) *oauth2.Config {
}
}

func (c *gitlabConnector) LoginURL(scopes connector.Scopes, callbackURL, state string) (string, error) {
func (c *gitlabConnector) LoginURL(scopes connector.Scopes, callbackURL, state string) (string, []byte, error) {
if c.redirectURI != callbackURL {
return "", fmt.Errorf("expected callback URL %q did not match the URL in the config %q", c.redirectURI, callbackURL)
return "", nil, fmt.Errorf("expected callback URL %q did not match the URL in the config %q", c.redirectURI, callbackURL)
}
return c.oauth2Config(scopes).AuthCodeURL(state), nil
return c.oauth2Config(scopes).AuthCodeURL(state), nil, nil
}

type oauth2Error struct {
Expand All @@ -109,7 +109,7 @@ func (e *oauth2Error) Error() string {
return e.error + ": " + e.errorDescription
}

func (c *gitlabConnector) HandleCallback(s connector.Scopes, r *http.Request) (identity connector.Identity, err error) {
func (c *gitlabConnector) HandleCallback(s connector.Scopes, r *http.Request, connDataBytes []byte) (identity connector.Identity, err error) {
q := r.URL.Query()
if errType := q.Get("error"); errType != "" {
return identity, &oauth2Error{errType, q.Get("error_description")}
Expand Down
8 changes: 4 additions & 4 deletions connector/linkedin/linkedin.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,17 @@ var (
)

// LoginURL returns an access token request URL
func (c *linkedInConnector) LoginURL(scopes connector.Scopes, callbackURL, state string) (string, error) {
func (c *linkedInConnector) LoginURL(scopes connector.Scopes, callbackURL, state string) (string, []byte, error) {
if c.oauth2Config.RedirectURL != callbackURL {
return "", fmt.Errorf("expected callback URL %q did not match the URL in the config %q",
return "", nil, fmt.Errorf("expected callback URL %q did not match the URL in the config %q",
callbackURL, c.oauth2Config.RedirectURL)
}

return c.oauth2Config.AuthCodeURL(state), nil
return c.oauth2Config.AuthCodeURL(state), nil, nil
}

// HandleCallback handles HTTP redirect from LinkedIn
func (c *linkedInConnector) HandleCallback(s connector.Scopes, r *http.Request) (identity connector.Identity, err error) {
func (c *linkedInConnector) HandleCallback(s connector.Scopes, r *http.Request, connDataBytes []byte) (identity connector.Identity, err error) {
q := r.URL.Query()
if errType := q.Get("error"); errType != "" {
return identity, &oauth2Error{errType, q.Get("error_description")}
Expand Down
8 changes: 4 additions & 4 deletions connector/microsoft/microsoft.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,15 @@ func (c *microsoftConnector) oauth2Config(scopes connector.Scopes) *oauth2.Confi
}
}

func (c *microsoftConnector) LoginURL(scopes connector.Scopes, callbackURL, state string) (string, error) {
func (c *microsoftConnector) LoginURL(scopes connector.Scopes, callbackURL, state string) (string, []byte, error) {
if c.redirectURI != callbackURL {
return "", fmt.Errorf("expected callback URL %q did not match the URL in the config %q", callbackURL, c.redirectURI)
return "", nil, fmt.Errorf("expected callback URL %q did not match the URL in the config %q", callbackURL, c.redirectURI)
}

return c.oauth2Config(scopes).AuthCodeURL(state), nil
return c.oauth2Config(scopes).AuthCodeURL(state), nil, nil
}

func (c *microsoftConnector) HandleCallback(s connector.Scopes, r *http.Request) (identity connector.Identity, err error) {
func (c *microsoftConnector) HandleCallback(s connector.Scopes, r *http.Request, connDataBytes []byte) (identity connector.Identity, err error) {
q := r.URL.Query()
if errType := q.Get("error"); errType != "" {
return identity, &oauth2Error{errType, q.Get("error_description")}
Expand Down
8 changes: 4 additions & 4 deletions connector/mock/connectortest.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,21 @@ type Callback struct {
}

// LoginURL returns the URL to redirect the user to login with.
func (m *Callback) LoginURL(s connector.Scopes, callbackURL, state string) (string, error) {
func (m *Callback) LoginURL(s connector.Scopes, callbackURL, state string) (string, []byte, error) {
u, err := url.Parse(callbackURL)
if err != nil {
return "", fmt.Errorf("failed to parse callbackURL %q: %v", callbackURL, err)
return "", nil, fmt.Errorf("failed to parse callbackURL %q: %v", callbackURL, err)
}
v := u.Query()
v.Set("state", state)
u.RawQuery = v.Encode()
return u.String(), nil
return u.String(), nil, nil
}

var connectorData = []byte("foobar")

// HandleCallback parses the request and returns the user's identity
func (m *Callback) HandleCallback(s connector.Scopes, r *http.Request) (connector.Identity, error) {
func (m *Callback) HandleCallback(s connector.Scopes, r *http.Request, connDataBytes []byte) (connector.Identity, error) {
return m.Identity, nil
}

Expand Down
Loading

0 comments on commit 9ff5eb1

Please sign in to comment.