Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GH-372] Fix unmarshaling issue with Wordpress strategy connections #398

Merged
merged 2 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions management/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"sort"
"strings"

"github.com/auth0/go-auth0"
"github.com/auth0/go-auth0/internal/tag"
)

Expand Down Expand Up @@ -913,6 +914,58 @@ type ConnectionOptionsOAuth2 struct {
UpstreamParams map[string]interface{} `json:"upstream_params,omitempty"`
}

// UnmarshalJSON implements the json.Unmarshaler interface for ConnectionOptionsOAuth2.
// It is required to handle differences in the scope field, which can
// be an array of strings or a single string.
func (c *ConnectionOptionsOAuth2) UnmarshalJSON(data []byte) error {
type connectionOptionsOAuth2 ConnectionOptionsOAuth2
type connectionOptionsOAuth2Wrapper struct {
*connectionOptionsOAuth2
RawScope interface{} `json:"scope,omitempty"`
}

alias := &connectionOptionsOAuth2Wrapper{(*connectionOptionsOAuth2)(c), nil}

err := json.Unmarshal(data, alias)
if err != nil {
return err
}

if alias.RawScope != nil {
switch rawScope := alias.RawScope.(type) {
case []interface{}:
scopes := make([]string, len(rawScope))
for i, v := range rawScope {
scopes[i] = v.(string)
}
c.Scope = auth0.String(strings.Join(scopes, " "))
case string:
c.Scope = auth0.String(rawScope)
default:
return fmt.Errorf("unexpected type for field scope: %T", alias.RawScope)
}
}

return nil
}

// MarshalJSON implements the json.Marshaler interface for ConnectionOptionsOAuth2.
func (c *ConnectionOptionsOAuth2) MarshalJSON() ([]byte, error) {
type connectionOptionsOAuth2 ConnectionOptionsOAuth2
type connectionOptionsOAuth2Wrapper struct {
*connectionOptionsOAuth2
RawScope interface{} `json:"scope,omitempty"`
}

alias := &connectionOptionsOAuth2Wrapper{(*connectionOptionsOAuth2)(c), nil}
if c.Scope != nil {
scopes := strings.Fields(*c.Scope)
alias.RawScope = scopes
}

return json.Marshal(alias)
}

// Scopes returns the scopes for ConnectionOptionsOAuth2.
func (c *ConnectionOptionsOAuth2) Scopes() []string {
return strings.Fields(c.GetScope())
Expand Down
41 changes: 41 additions & 0 deletions management/connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ var connectionTestCases = []connectionTestCase{
},
},
},
{
name: "Wordpress Connection",
connection: Connection{
Name: auth0.Stringf("Test-Wordpress-Connection-%d", time.Now().Unix()),
Strategy: auth0.String("wordpress"),
},
options: &ConnectionOptionsOAuth2{
Scope: auth0.String("email profile openid"),
UpstreamParams: map[string]interface{}{
"screen_name": map[string]interface{}{
"alias": "login_hint",
},
},
},
},
{
name: "GoogleOAuth2 Connection",
connection: Connection{
Expand Down Expand Up @@ -612,6 +627,32 @@ func TestConnectionOptionsScopes(t *testing.T) {
})
}

func TestOAuth2Connection_MarshalJSON(t *testing.T) {
for connection, expected := range map[*ConnectionOptionsOAuth2]string{
{Scope: auth0.String("foo bar baz")}: `{"authorizationURL":null,"tokenURL":null,"scope":["foo","bar","baz"]}`,
{Scope: auth0.String("")}: `{"authorizationURL":null,"tokenURL":null,"scope":[]}`,
{Scope: nil}: `{"authorizationURL":null,"tokenURL":null}`,
} {
payload, err := json.Marshal(connection)
assert.NoError(t, err)
assert.Equal(t, expected, string(payload))
}
}

func TestOAuth2Connection_UnmarshalJSON(t *testing.T) {
for expectedAsString, expected := range map[string]*ConnectionOptionsOAuth2{
`{"scope":["foo","bar","baz"]}`: {Scope: auth0.String("foo bar baz")},
`{"scope":null}`: {Scope: nil},
`{}`: {},
`{"scope":[]}`: {Scope: auth0.String("")},
} {
var actual *ConnectionOptionsOAuth2
err := json.Unmarshal([]byte(expectedAsString), &actual)
assert.NoError(t, err)
assert.Equal(t, expected, actual)
}
}

func TestGoogleOauth2Connection_MarshalJSON(t *testing.T) {
var emptySlice []string
for connection, expected := range map[*ConnectionOptionsGoogleOAuth2]string{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interactions:
remote_addr: ""
request_uri: ""
body: |
{"name":"Test-ADFS-Connection-1714039090","strategy":"adfs","options":{"fedMetadataXml":"\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cEntityDescriptor entityID=\"https://example.com\"\n xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\"\u003e\n \u003cRoleDescriptor xsi:type=\"fed:ApplicationServiceType\"\n protocolSupportEnumeration=\"http://docs.oasis-open.org/wsfed/federation/200706\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:fed=\"http://docs.oasis-open.org/wsfed/federation/200706\"\u003e\n \u003cfed:TargetScopes\u003e\n \u003cwsa:EndpointReference xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"\u003e\n \u003cwsa:Address\u003ehttps://adfs.provider/\u003c/wsa:Address\u003e\n \u003c/wsa:EndpointReference\u003e\n \u003c/fed:TargetScopes\u003e\n \u003cfed:ApplicationServiceEndpoint\u003e\n \u003cwsa:EndpointReference xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"\u003e\n \u003cwsa:Address\u003ehttps://adfs.provider/wsfed\u003c/wsa:Address\u003e\n \u003c/wsa:EndpointReference\u003e\n \u003c/fed:ApplicationServiceEndpoint\u003e\n \u003cfed:PassiveRequestorEndpoint\u003e\n \u003cwsa:EndpointReference xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"\u003e\n \u003cwsa:Address\u003ehttps://adfs.provider/wsfed\u003c/wsa:Address\u003e\n \u003c/wsa:EndpointReference\u003e\n \u003c/fed:PassiveRequestorEndpoint\u003e\n \u003c/RoleDescriptor\u003e\n \u003cIDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\"\u003e\n \u003cSingleLogoutService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"\n Location=\"https://adfs.provider/sign_out\"/\u003e\n \u003cSingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"\n Location=\"https://adfs.provider/sign_in\"/\u003e\n \u003c/IDPSSODescriptor\u003e\n\u003c/EntityDescriptor\u003e\n","upstream_params":{"screen_name":{"alias":"login_hint"}}}}
{"name":"Test-ADFS-Connection-1714473052","strategy":"adfs","options":{"fedMetadataXml":"\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cEntityDescriptor entityID=\"https://example.com\"\n xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\"\u003e\n \u003cRoleDescriptor xsi:type=\"fed:ApplicationServiceType\"\n protocolSupportEnumeration=\"http://docs.oasis-open.org/wsfed/federation/200706\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:fed=\"http://docs.oasis-open.org/wsfed/federation/200706\"\u003e\n \u003cfed:TargetScopes\u003e\n \u003cwsa:EndpointReference xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"\u003e\n \u003cwsa:Address\u003ehttps://adfs.provider/\u003c/wsa:Address\u003e\n \u003c/wsa:EndpointReference\u003e\n \u003c/fed:TargetScopes\u003e\n \u003cfed:ApplicationServiceEndpoint\u003e\n \u003cwsa:EndpointReference xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"\u003e\n \u003cwsa:Address\u003ehttps://adfs.provider/wsfed\u003c/wsa:Address\u003e\n \u003c/wsa:EndpointReference\u003e\n \u003c/fed:ApplicationServiceEndpoint\u003e\n \u003cfed:PassiveRequestorEndpoint\u003e\n \u003cwsa:EndpointReference xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"\u003e\n \u003cwsa:Address\u003ehttps://adfs.provider/wsfed\u003c/wsa:Address\u003e\n \u003c/wsa:EndpointReference\u003e\n \u003c/fed:PassiveRequestorEndpoint\u003e\n \u003c/RoleDescriptor\u003e\n \u003cIDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\"\u003e\n \u003cSingleLogoutService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"\n Location=\"https://adfs.provider/sign_out\"/\u003e\n \u003cSingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"\n Location=\"https://adfs.provider/sign_in\"/\u003e\n \u003c/IDPSSODescriptor\u003e\n\u003c/EntityDescriptor\u003e\n","upstream_params":{"screen_name":{"alias":"login_hint"}}}}
form: {}
headers:
Content-Type:
Expand All @@ -30,13 +30,13 @@ interactions:
trailer: {}
content_length: -1
uncompressed: false
body: '{"id":"con_99dCf1MTlQiNP56U","options":{"fedMetadataXml":"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<EntityDescriptor entityID=\"https://example.com\"\n xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\">\n <RoleDescriptor xsi:type=\"fed:ApplicationServiceType\"\n protocolSupportEnumeration=\"http://docs.oasis-open.org/wsfed/federation/200706\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:fed=\"http://docs.oasis-open.org/wsfed/federation/200706\">\n <fed:TargetScopes>\n <wsa:EndpointReference xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">\n <wsa:Address>https://adfs.provider/</wsa:Address>\n </wsa:EndpointReference>\n </fed:TargetScopes>\n <fed:ApplicationServiceEndpoint>\n <wsa:EndpointReference xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">\n <wsa:Address>https://adfs.provider/wsfed</wsa:Address>\n </wsa:EndpointReference>\n </fed:ApplicationServiceEndpoint>\n <fed:PassiveRequestorEndpoint>\n <wsa:EndpointReference xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">\n <wsa:Address>https://adfs.provider/wsfed</wsa:Address>\n </wsa:EndpointReference>\n </fed:PassiveRequestorEndpoint>\n </RoleDescriptor>\n <IDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\">\n <SingleLogoutService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"\n Location=\"https://adfs.provider/sign_out\"/>\n <SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"\n Location=\"https://adfs.provider/sign_in\"/>\n </IDPSSODescriptor>\n</EntityDescriptor>\n","upstream_params":{"screen_name":{"alias":"login_hint"}},"thumbprints":[],"signInEndpoint":"https://adfs.provider/wsfed","should_trust_email_verified_connection":"always_set_emails_as_verified"},"strategy":"adfs","name":"Test-ADFS-Connection-1714039090","provisioning_ticket_url":"https://go-auth0-dev.eu.auth0.com.us.auth0.com/p/adfs/8Il6A5Qd","is_domain_connection":false,"show_as_button":false,"enabled_clients":[],"realms":["Test-ADFS-Connection-1714039090"]}'
body: '{"id":"con_0395zVLxXGz37nxg","options":{"fedMetadataXml":"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<EntityDescriptor entityID=\"https://example.com\"\n xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\">\n <RoleDescriptor xsi:type=\"fed:ApplicationServiceType\"\n protocolSupportEnumeration=\"http://docs.oasis-open.org/wsfed/federation/200706\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:fed=\"http://docs.oasis-open.org/wsfed/federation/200706\">\n <fed:TargetScopes>\n <wsa:EndpointReference xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">\n <wsa:Address>https://adfs.provider/</wsa:Address>\n </wsa:EndpointReference>\n </fed:TargetScopes>\n <fed:ApplicationServiceEndpoint>\n <wsa:EndpointReference xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">\n <wsa:Address>https://adfs.provider/wsfed</wsa:Address>\n </wsa:EndpointReference>\n </fed:ApplicationServiceEndpoint>\n <fed:PassiveRequestorEndpoint>\n <wsa:EndpointReference xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">\n <wsa:Address>https://adfs.provider/wsfed</wsa:Address>\n </wsa:EndpointReference>\n </fed:PassiveRequestorEndpoint>\n </RoleDescriptor>\n <IDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\">\n <SingleLogoutService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"\n Location=\"https://adfs.provider/sign_out\"/>\n <SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"\n Location=\"https://adfs.provider/sign_in\"/>\n </IDPSSODescriptor>\n</EntityDescriptor>\n","upstream_params":{"screen_name":{"alias":"login_hint"}},"thumbprints":[],"signInEndpoint":"https://adfs.provider/wsfed","should_trust_email_verified_connection":"always_set_emails_as_verified"},"strategy":"adfs","name":"Test-ADFS-Connection-1714473052","provisioning_ticket_url":"https://go-auth0-dev.eu.auth0.com.us.auth0.com/p/adfs/s3WGmg3a","is_domain_connection":false,"show_as_button":false,"enabled_clients":[],"realms":["Test-ADFS-Connection-1714473052"]}'
headers:
Content-Type:
- application/json; charset=utf-8
status: 201 Created
code: 201
duration: 317.085292ms
duration: 383.956ms
- id: 1
request:
proto: HTTP/1.1
Expand All @@ -55,7 +55,7 @@ interactions:
- application/json
User-Agent:
- Go-Auth0/1.5.0
url: https://go-auth0-dev.eu.auth0.com/api/v2/connections/con_99dCf1MTlQiNP56U
url: https://go-auth0-dev.eu.auth0.com/api/v2/connections/con_0395zVLxXGz37nxg
method: DELETE
response:
proto: HTTP/2.0
Expand All @@ -65,10 +65,10 @@ interactions:
trailer: {}
content_length: 41
uncompressed: false
body: '{"deleted_at":"2024-04-25T09:58:17.762Z"}'
body: '{"deleted_at":"2024-04-30T10:31:00.646Z"}'
headers:
Content-Type:
- application/json; charset=utf-8
status: 202 Accepted
code: 202
duration: 289.661625ms
duration: 366.961792ms
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interactions:
remote_addr: ""
request_uri: ""
body: |
{"name":"Test-AD-Connection-1714039090","strategy":"ad","options":{"upstream_params":{"screen_name":{"alias":"login_hint"}}}}
{"name":"Test-AD-Connection-1714473052","strategy":"ad","options":{"upstream_params":{"screen_name":{"alias":"login_hint"}}}}
form: {}
headers:
Content-Type:
Expand All @@ -30,13 +30,13 @@ interactions:
trailer: {}
content_length: 407
uncompressed: false
body: '{"id":"con_HzF4tG8cdHmnnn30","options":{"upstream_params":{"screen_name":{"alias":"login_hint"}},"ips":null,"brute_force_protection":true},"strategy":"ad","name":"Test-AD-Connection-1714039090","provisioning_ticket_url":"https://go-auth0-dev.eu.auth0.com.us.auth0.com/p/ad/ITTPn4ckD4O3R2JUiLJl0h0NjGGlBotS","is_domain_connection":false,"show_as_button":false,"enabled_clients":[],"realms":["Test-AD-Connection-1714039090"]}'
body: '{"id":"con_pbVKvqxBHFr6oWPj","options":{"upstream_params":{"screen_name":{"alias":"login_hint"}},"ips":null,"brute_force_protection":true},"strategy":"ad","name":"Test-AD-Connection-1714473052","provisioning_ticket_url":"https://go-auth0-dev.eu.auth0.com.us.auth0.com/p/ad/ebkio6LUEGJu1ohysbIlQybdZ3Imrm3A","is_domain_connection":false,"show_as_button":false,"enabled_clients":[],"realms":["Test-AD-Connection-1714473052"]}'
headers:
Content-Type:
- application/json; charset=utf-8
status: 201 Created
code: 201
duration: 329.268584ms
duration: 406.856083ms
- id: 1
request:
proto: HTTP/1.1
Expand All @@ -55,7 +55,7 @@ interactions:
- application/json
User-Agent:
- Go-Auth0/1.5.0
url: https://go-auth0-dev.eu.auth0.com/api/v2/connections/con_HzF4tG8cdHmnnn30
url: https://go-auth0-dev.eu.auth0.com/api/v2/connections/con_pbVKvqxBHFr6oWPj
method: DELETE
response:
proto: HTTP/2.0
Expand All @@ -65,10 +65,10 @@ interactions:
trailer: {}
content_length: 41
uncompressed: false
body: '{"deleted_at":"2024-04-25T09:58:17.153Z"}'
body: '{"deleted_at":"2024-04-30T10:30:59.908Z"}'
headers:
Content-Type:
- application/json; charset=utf-8
status: 202 Accepted
code: 202
duration: 298.261542ms
duration: 329.858125ms
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interactions:
remote_addr: ""
request_uri: ""
body: |
{"name":"Test-Apple-Connection-1714039090","strategy":"apple","options":{"upstream_params":{"screen_name":{"alias":"login_hint"}}}}
{"name":"Test-Apple-Connection-1714473052","strategy":"apple","options":{"upstream_params":{"screen_name":{"alias":"login_hint"}}}}
form: {}
headers:
Content-Type:
Expand All @@ -30,13 +30,13 @@ interactions:
trailer: {}
content_length: 255
uncompressed: false
body: '{"id":"con_Y8Kj7ui38hZiC8fp","options":{"upstream_params":{"screen_name":{"alias":"login_hint"}}},"strategy":"apple","name":"Test-Apple-Connection-1714039090","is_domain_connection":false,"enabled_clients":[],"realms":["Test-Apple-Connection-1714039090"]}'
body: '{"id":"con_vweVu7ZlaTbdM5C0","options":{"upstream_params":{"screen_name":{"alias":"login_hint"}}},"strategy":"apple","name":"Test-Apple-Connection-1714473052","is_domain_connection":false,"enabled_clients":[],"realms":["Test-Apple-Connection-1714473052"]}'
headers:
Content-Type:
- application/json; charset=utf-8
status: 201 Created
code: 201
duration: 304.10175ms
duration: 363.491583ms
- id: 1
request:
proto: HTTP/1.1
Expand All @@ -55,7 +55,7 @@ interactions:
- application/json
User-Agent:
- Go-Auth0/1.5.0
url: https://go-auth0-dev.eu.auth0.com/api/v2/connections/con_Y8Kj7ui38hZiC8fp
url: https://go-auth0-dev.eu.auth0.com/api/v2/connections/con_vweVu7ZlaTbdM5C0
method: DELETE
response:
proto: HTTP/2.0
Expand All @@ -65,10 +65,10 @@ interactions:
trailer: {}
content_length: 41
uncompressed: false
body: '{"deleted_at":"2024-04-25T09:58:19.013Z"}'
body: '{"deleted_at":"2024-04-30T10:31:02.076Z"}'
headers:
Content-Type:
- application/json; charset=utf-8
status: 202 Accepted
code: 202
duration: 302.679292ms
duration: 358.612958ms
Loading