Skip to content

Commit

Permalink
disco: Support OAuth scopes in OAuth client discovery
Browse files Browse the repository at this point in the history
Support for scopes is required for OAuth2 server
implementations that are following the additional
requirements imposed by the OpenID Connect
specification.
  • Loading branch information
jceresini authored and apparentlymart committed Jul 29, 2020
1 parent cf9d221 commit 4ec0a82
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 0 deletions.
11 changes: 11 additions & 0 deletions disco/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,17 @@ func (h *Host) ServiceOAuthClient(id string) (*OAuthClient, error) {
ret.MinPort = 1024
ret.MaxPort = 65535
}
if scopesRaw, ok := raw["scopes"].([]interface{}); ok {
var scopes []string
for _, scopeI := range scopesRaw {
scope, ok := scopeI.(string)
if !ok {
return nil, fmt.Errorf("Invalid \"scopes\" for service %s: all scopes must be strings", id)
}
scopes = append(scopes, scope)
}
ret.Scopes = scopes
}

return ret, nil
}
Expand Down
48 changes: 48 additions & 0 deletions disco/host_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,24 @@ func TestHostServiceOAuthClient(t *testing.T) {
"authz": "/foo",
"token": "***not A URL at all!:/<@@@@>***",
},
"scopesincluded.v1": map[string]interface{}{
"client": "scopesincluded",
"authz": "/auth",
"token": "/token",
"scopes": []interface{}{"app1.full_access", "app2.read_only"},
},
"scopesempty.v1": map[string]interface{}{
"client": "scopesempty",
"authz": "/auth",
"token": "/token",
"scopes": []interface{}{},
},
"scopesbad.v1": map[string]interface{}{
"client": "scopesbad",
"authz": "/auth",
"token": "/token",
"scopes": []interface{}{"app1.full_access", 42},
},
},
}

Expand Down Expand Up @@ -290,6 +308,36 @@ func TestHostServiceOAuthClient(t *testing.T) {
nil,
"Failed to parse token URL: parse \"***not A URL at all!:/<@@@@>***\": first path segment in URL cannot contain colon",
},
{
"scopesincluded.v1",
&OAuthClient{
ID: "scopesincluded",
AuthorizationURL: mustURL(t, "https://example.com/auth"),
TokenURL: mustURL(t, "https://example.com/token"),
MinPort: 1024,
MaxPort: 65535,
SupportedGrantTypes: NewOAuthGrantTypeSet("authz_code"),
Scopes: []string{"app1.full_access", "app2.read_only"},
},
"",
},
{
"scopesempty.v1",
&OAuthClient{
ID: "scopesempty",
AuthorizationURL: mustURL(t, "https://example.com/auth"),
TokenURL: mustURL(t, "https://example.com/token"),
MinPort: 1024,
MaxPort: 65535,
SupportedGrantTypes: NewOAuthGrantTypeSet("authz_code"),
},
"",
},
{
"scopesbad.v1",
nil,
`Invalid "scopes" for service scopesbad.v1: all scopes must be strings`,
},
}

for _, test := range tests {
Expand Down
5 changes: 5 additions & 0 deletions disco/oauth_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ type OAuthClient struct {
// by the server, even if a particular keyword is not supported by the
// current version of Terraform.
SupportedGrantTypes OAuthGrantTypeSet

// Oauth2 does not require scopes for the authorization endpoint, however
// OIDC does. Optional list of scopes to include in auth code and token
// requests.
Scopes []string
}

// Endpoint returns an oauth2.Endpoint value ready to be used with the oauth2
Expand Down

0 comments on commit 4ec0a82

Please sign in to comment.