From 48fdb62a0b9b8f0e1327d14642dd404448798d13 Mon Sep 17 00:00:00 2001 From: Ewan Harris Date: Fri, 10 Mar 2023 16:27:55 +0000 Subject: [PATCH] Add Factor Management endpoints --- management/management.gen.go | 159 ++++++ management/management.gen_test.go | 204 ++++++++ management/user.go | 102 ++++ management/user_test.go | 72 +++ ...TestUserManager_AuthenticationMethods.yaml | 468 ++++++++++++++++++ 5 files changed, 1005 insertions(+) create mode 100644 test/data/recordings/TestUserManager_AuthenticationMethods.yaml diff --git a/management/management.gen.go b/management/management.gen.go index a5290496..f166b1d5 100644 --- a/management/management.gen.go +++ b/management/management.gen.go @@ -479,6 +479,165 @@ func (a *ActionVersionList) String() string { return Stringify(a) } +// GetAuthenticationMethods returns the AuthenticationMethods field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetAuthenticationMethods() []AuthenticationMethodReference { + if a == nil || a.AuthenticationMethods == nil { + return nil + } + return *a.AuthenticationMethods +} + +// GetConfirmed returns the Confirmed field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetConfirmed() bool { + if a == nil || a.Confirmed == nil { + return false + } + return *a.Confirmed +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetCreatedAt() time.Time { + if a == nil || a.CreatedAt == nil { + return time.Time{} + } + return *a.CreatedAt +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetEmail() string { + if a == nil || a.Email == nil { + return "" + } + return *a.Email +} + +// GetEnrolledAt returns the EnrolledAt field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetEnrolledAt() time.Time { + if a == nil || a.EnrolledAt == nil { + return time.Time{} + } + return *a.EnrolledAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetID() string { + if a == nil || a.ID == nil { + return "" + } + return *a.ID +} + +// GetKeyId returns the KeyId field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetKeyId() string { + if a == nil || a.KeyId == nil { + return "" + } + return *a.KeyId +} + +// GetLastAuthedAt returns the LastAuthedAt field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetLastAuthedAt() time.Time { + if a == nil || a.LastAuthedAt == nil { + return time.Time{} + } + return *a.LastAuthedAt +} + +// GetLinkID returns the LinkID field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetLinkID() string { + if a == nil || a.LinkID == nil { + return "" + } + return *a.LinkID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetPhoneNumber returns the PhoneNumber field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetPhoneNumber() string { + if a == nil || a.PhoneNumber == nil { + return "" + } + return *a.PhoneNumber +} + +// GetPreferredAuthenticationMethod returns the PreferredAuthenticationMethod field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetPreferredAuthenticationMethod() string { + if a == nil || a.PreferredAuthenticationMethod == nil { + return "" + } + return *a.PreferredAuthenticationMethod +} + +// GetPublicKey returns the PublicKey field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetPublicKey() string { + if a == nil || a.PublicKey == nil { + return "" + } + return *a.PublicKey +} + +// GetRelyingPartyIdentifier returns the RelyingPartyIdentifier field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetRelyingPartyIdentifier() string { + if a == nil || a.RelyingPartyIdentifier == nil { + return "" + } + return *a.RelyingPartyIdentifier +} + +// GetTOTPSecret returns the TOTPSecret field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetTOTPSecret() string { + if a == nil || a.TOTPSecret == nil { + return "" + } + return *a.TOTPSecret +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethod) GetType() string { + if a == nil || a.Type == nil { + return "" + } + return *a.Type +} + +// String returns a string representation of AuthenticationMethod. +func (a *AuthenticationMethod) String() string { + return Stringify(a) +} + +// String returns a string representation of AuthenticationMethodList. +func (a *AuthenticationMethodList) String() string { + return Stringify(a) +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethodReference) GetID() string { + if a == nil || a.ID == nil { + return "" + } + return *a.ID +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (a *AuthenticationMethodReference) GetType() string { + if a == nil || a.Type == nil { + return "" + } + return *a.Type +} + +// String returns a string representation of AuthenticationMethodReference. +func (a *AuthenticationMethodReference) String() string { + return Stringify(a) +} + // String returns a string representation of BlacklistToken. func (b *BlacklistToken) String() string { return Stringify(b) diff --git a/management/management.gen_test.go b/management/management.gen_test.go index df0247fb..1ae95d03 100644 --- a/management/management.gen_test.go +++ b/management/management.gen_test.go @@ -615,6 +615,210 @@ func TestActionVersionList_String(t *testing.T) { } } +func TestAuthenticationMethod_GetAuthenticationMethods(tt *testing.T) { + var zeroValue []AuthenticationMethodReference + a := &AuthenticationMethod{AuthenticationMethods: &zeroValue} + a.GetAuthenticationMethods() + a = &AuthenticationMethod{} + a.GetAuthenticationMethods() + a = nil + a.GetAuthenticationMethods() +} + +func TestAuthenticationMethod_GetConfirmed(tt *testing.T) { + var zeroValue bool + a := &AuthenticationMethod{Confirmed: &zeroValue} + a.GetConfirmed() + a = &AuthenticationMethod{} + a.GetConfirmed() + a = nil + a.GetConfirmed() +} + +func TestAuthenticationMethod_GetCreatedAt(tt *testing.T) { + var zeroValue time.Time + a := &AuthenticationMethod{CreatedAt: &zeroValue} + a.GetCreatedAt() + a = &AuthenticationMethod{} + a.GetCreatedAt() + a = nil + a.GetCreatedAt() +} + +func TestAuthenticationMethod_GetEmail(tt *testing.T) { + var zeroValue string + a := &AuthenticationMethod{Email: &zeroValue} + a.GetEmail() + a = &AuthenticationMethod{} + a.GetEmail() + a = nil + a.GetEmail() +} + +func TestAuthenticationMethod_GetEnrolledAt(tt *testing.T) { + var zeroValue time.Time + a := &AuthenticationMethod{EnrolledAt: &zeroValue} + a.GetEnrolledAt() + a = &AuthenticationMethod{} + a.GetEnrolledAt() + a = nil + a.GetEnrolledAt() +} + +func TestAuthenticationMethod_GetID(tt *testing.T) { + var zeroValue string + a := &AuthenticationMethod{ID: &zeroValue} + a.GetID() + a = &AuthenticationMethod{} + a.GetID() + a = nil + a.GetID() +} + +func TestAuthenticationMethod_GetKeyId(tt *testing.T) { + var zeroValue string + a := &AuthenticationMethod{KeyId: &zeroValue} + a.GetKeyId() + a = &AuthenticationMethod{} + a.GetKeyId() + a = nil + a.GetKeyId() +} + +func TestAuthenticationMethod_GetLastAuthedAt(tt *testing.T) { + var zeroValue time.Time + a := &AuthenticationMethod{LastAuthedAt: &zeroValue} + a.GetLastAuthedAt() + a = &AuthenticationMethod{} + a.GetLastAuthedAt() + a = nil + a.GetLastAuthedAt() +} + +func TestAuthenticationMethod_GetLinkID(tt *testing.T) { + var zeroValue string + a := &AuthenticationMethod{LinkID: &zeroValue} + a.GetLinkID() + a = &AuthenticationMethod{} + a.GetLinkID() + a = nil + a.GetLinkID() +} + +func TestAuthenticationMethod_GetName(tt *testing.T) { + var zeroValue string + a := &AuthenticationMethod{Name: &zeroValue} + a.GetName() + a = &AuthenticationMethod{} + a.GetName() + a = nil + a.GetName() +} + +func TestAuthenticationMethod_GetPhoneNumber(tt *testing.T) { + var zeroValue string + a := &AuthenticationMethod{PhoneNumber: &zeroValue} + a.GetPhoneNumber() + a = &AuthenticationMethod{} + a.GetPhoneNumber() + a = nil + a.GetPhoneNumber() +} + +func TestAuthenticationMethod_GetPreferredAuthenticationMethod(tt *testing.T) { + var zeroValue string + a := &AuthenticationMethod{PreferredAuthenticationMethod: &zeroValue} + a.GetPreferredAuthenticationMethod() + a = &AuthenticationMethod{} + a.GetPreferredAuthenticationMethod() + a = nil + a.GetPreferredAuthenticationMethod() +} + +func TestAuthenticationMethod_GetPublicKey(tt *testing.T) { + var zeroValue string + a := &AuthenticationMethod{PublicKey: &zeroValue} + a.GetPublicKey() + a = &AuthenticationMethod{} + a.GetPublicKey() + a = nil + a.GetPublicKey() +} + +func TestAuthenticationMethod_GetRelyingPartyIdentifier(tt *testing.T) { + var zeroValue string + a := &AuthenticationMethod{RelyingPartyIdentifier: &zeroValue} + a.GetRelyingPartyIdentifier() + a = &AuthenticationMethod{} + a.GetRelyingPartyIdentifier() + a = nil + a.GetRelyingPartyIdentifier() +} + +func TestAuthenticationMethod_GetTOTPSecret(tt *testing.T) { + var zeroValue string + a := &AuthenticationMethod{TOTPSecret: &zeroValue} + a.GetTOTPSecret() + a = &AuthenticationMethod{} + a.GetTOTPSecret() + a = nil + a.GetTOTPSecret() +} + +func TestAuthenticationMethod_GetType(tt *testing.T) { + var zeroValue string + a := &AuthenticationMethod{Type: &zeroValue} + a.GetType() + a = &AuthenticationMethod{} + a.GetType() + a = nil + a.GetType() +} + +func TestAuthenticationMethod_String(t *testing.T) { + var rawJSON json.RawMessage + v := &AuthenticationMethod{} + if err := json.Unmarshal([]byte(v.String()), &rawJSON); err != nil { + t.Errorf("failed to produce a valid json") + } +} + +func TestAuthenticationMethodList_String(t *testing.T) { + var rawJSON json.RawMessage + v := &AuthenticationMethodList{} + if err := json.Unmarshal([]byte(v.String()), &rawJSON); err != nil { + t.Errorf("failed to produce a valid json") + } +} + +func TestAuthenticationMethodReference_GetID(tt *testing.T) { + var zeroValue string + a := &AuthenticationMethodReference{ID: &zeroValue} + a.GetID() + a = &AuthenticationMethodReference{} + a.GetID() + a = nil + a.GetID() +} + +func TestAuthenticationMethodReference_GetType(tt *testing.T) { + var zeroValue string + a := &AuthenticationMethodReference{Type: &zeroValue} + a.GetType() + a = &AuthenticationMethodReference{} + a.GetType() + a = nil + a.GetType() +} + +func TestAuthenticationMethodReference_String(t *testing.T) { + var rawJSON json.RawMessage + v := &AuthenticationMethodReference{} + if err := json.Unmarshal([]byte(v.String()), &rawJSON); err != nil { + t.Errorf("failed to produce a valid json") + } +} + func TestBlacklistToken_String(t *testing.T) { var rawJSON json.RawMessage v := &BlacklistToken{} diff --git a/management/user.go b/management/user.go index f52271f6..40049442 100644 --- a/management/user.go +++ b/management/user.go @@ -305,6 +305,52 @@ type UserList struct { Users []*User `json:"users"` } +type AuthenticationMethod struct { + // The ID of the authentication method (auto generated). + ID *string `json:"id,omitempty"` + // The type of the authentication method. Should be one of "phone", "email", "totp" or "webauthn-roaming". + Type *string `json:"type,omitempty"` + // The authentication method status. + Confirmed *bool `json:"confirmed,omitempty"` + // A human-readable label to identify the authentication method. + Name *string `json:"name,omitempty"` + // The ID of a linked authentication method. Linked authentication methods will be deleted together. + LinkID *string `json:"link_id,omitempty"` + // Applies to phone authentication methods only. The destination phone number used to send verification codes via text and voice. + PhoneNumber *string `json:"phone_number,omitempty"` + // Applies to email authentication method only. The email address used to send verification messages. + Email *string `json:"email,omitempty"` + // Applies to webauthn authentication methods only. The ID of the generated credential. + KeyId *string `json:"key_id,omitempty"` + // Applies to webauthn authentication methods only. The public key. + PublicKey *string `json:"public_key,omitempty"` + // Authenticator creation date. + CreatedAt *time.Time `json:"created_at,omitempty"` + // Enrollment date. + EnrolledAt *time.Time `json:"enrolled_at,omitempty"` + // Last authentication. + LastAuthedAt *time.Time `json:"last_auth_at,omitempty"` + // Base32 encoded secret for TOTP generation. + TOTPSecret *string `json:"totp_secret,omitempty"` + // The authentication method preferred for phone authenticators. + PreferredAuthenticationMethod *string `json:"preferred_authentication_method,omitempty"` + // Applies to email webauthn authenticators only. The relying party identifier. + RelyingPartyIdentifier *string `json:"relying_party_identifier,omitempty"` + AuthenticationMethods *[]AuthenticationMethodReference `json:"authentication_methods,omitempty"` +} + +type AuthenticationMethodReference struct { + // The ID of the authentication method (auto generated). + ID *string `json:"id,omitempty"` + // The type of the authentication method. + Type *string `json:"type,omitempty"` +} + +type AuthenticationMethodList struct { + List + Authenticators []*AuthenticationMethod `json:"authenticators,omitempty"` +} + // UserManager manages Auth0 User resources. type UserManager struct { *Management @@ -580,3 +626,59 @@ func (m *UserManager) Organizations(id string, opts ...RequestOption) (p *Organi err = m.Request("GET", m.URI("users", id, "organizations"), &p, applyListDefaults(opts)) return } + +// Gets a list of authentication methods. +// +// See: https://auth0.com/docs/api/management/v2#!/Users/get_authentication_methods +func (m *UserManager) GetAuthenticationMethods(userId string, opts ...RequestOption) (a *AuthenticationMethodList, err error) { + err = m.Request("GET", m.URI("users", userId, "authentication-methods"), &a, applyListDefaults(opts)) + return +} + +// Gets a specific authentication method for a user. +// +// See: https://auth0.com/docs/api/management/v2#!/Users/get_authentication_methods_by_authentication_method_id +func (m *UserManager) GetAuthenticationMethodById(userId string, id string, opts ...RequestOption) (a *AuthenticationMethod, err error) { + err = m.Request("GET", m.URI("users", userId, "authentication-methods", id), &a, applyListDefaults(opts)) + return +} + +// Creates an authentication method for a user. +// +// See: https://auth0.com/docs/api/management/v2#!/Users/post_authentication_methods +func (m *UserManager) CreateAuthenticationMethod(userId string, a *AuthenticationMethod, opts ...RequestOption) (err error) { + err = m.Request("POST", m.URI("users", userId, "authentication-methods"), &a, opts...) + return +} + +// Updates all authentication methods by replacing them with the given ones.. +// +// See: https://auth0.com/docs/api/management/v2#!/Users/put_authentication_methods +func (m *UserManager) UpdateAllAuthenticationMethods(userId string, a *[]AuthenticationMethod, opts ...RequestOption) (err error) { + err = m.Request("PUT", m.URI("users", userId, "authentication-methods"), &a, opts...) + return +} + +// Updates an authentication method by ID. +// +// See: https://auth0.com/docs/api/management/v2#!/Users/patch_authentication_methods_by_authentication_method_id +func (m *UserManager) UpdateAuthenticationMethod(userId string, id string, a *AuthenticationMethod, opts ...RequestOption) (err error) { + err = m.Request("PATCH", m.URI("users", userId, "authentication-methods", id), &a, opts...) + return +} + +// Deletes an authentication method by ID +// +// See: https://auth0.com/docs/api/management/v2#!/Users/delete_authentication_methods_by_authentication_method_id +func (m *UserManager) DeleteAuthenticationMethod(userId string, id string, opts ...RequestOption) (err error) { + err = m.Request("DELETE", m.URI("users", userId, "authentication-methods", id), nil, opts...) + return +} + +// Deletes all authentication methods for the given user. +// +// See: https://auth0.com/docs/api/management/v2#!/Users/delete_authentication_methods +func (m *UserManager) DeleteAllAuthenticationMethods(userId string, opts ...RequestOption) (err error) { + err = m.Request("DELETE", m.URI("users", userId, "authentication-methods"), nil, opts...) + return +} diff --git a/management/user_test.go b/management/user_test.go index 3d7f54b9..ca5b3630 100644 --- a/management/user_test.go +++ b/management/user_test.go @@ -353,6 +353,78 @@ func TestUserIdentity_UnmarshalJSON(t *testing.T) { } } +func TestUserManager_AuthenticationMethods(t *testing.T) { + configureHTTPTestRecordings(t) + + user := givenAUser(t) + method := AuthenticationMethod{ + Name: auth0.String("Test"), + Type: auth0.String("email"), + Email: auth0.String(user.GetEmail()), + } + + err := api.User.CreateAuthenticationMethod(user.GetID(), &method) + assert.NoError(t, err) + + methods, err := api.User.GetAuthenticationMethods(user.GetID()) + assert.NoError(t, err) + assert.Len(t, methods.Authenticators, 1) + assert.Equal(t, method.GetID(), methods.Authenticators[0].GetID()) + + methodInfo, err := api.User.GetAuthenticationMethodById(user.GetID(), method.GetID()) + assert.NoError(t, err) + assert.Equal(t, method.GetID(), methodInfo.GetID()) + + err = api.User.UpdateAuthenticationMethod(user.GetID(), methodInfo.GetID(), &AuthenticationMethod{ + Name: auth0.String("Test2"), + }) + assert.NoError(t, err) + + methodInfo, err = api.User.GetAuthenticationMethodById(user.GetID(), method.GetID()) + assert.NoError(t, err) + assert.Equal(t, "Test2", methodInfo.GetName()) + + err = api.User.DeleteAuthenticationMethod(user.GetID(), method.GetID()) + assert.NoError(t, err) + + methods, err = api.User.GetAuthenticationMethods(user.GetID()) + assert.NoError(t, err) + assert.Len(t, methods.Authenticators, 0) + + updateMethods := []AuthenticationMethod{ + { + Type: auth0.String("email"), + Name: auth0.String("MyEmail"), + Email: auth0.String("foo@example.com"), + }, + { + Type: auth0.String("phone"), + Name: auth0.String("MyPhone"), + PhoneNumber: auth0.String("+44207183875044"), + PreferredAuthenticationMethod: auth0.String("sms"), + }, + { + Type: auth0.String("totp"), + Name: auth0.String("MyTotp"), + TOTPSecret: auth0.String("5HCWXIP2MJNSUBGYVUZFLRB2HWIGXR4SYJQXNBQ"), + }, + } + + err = api.User.UpdateAllAuthenticationMethods(user.GetID(), &updateMethods) + assert.NoError(t, err) + + methods, err = api.User.GetAuthenticationMethods(user.GetID()) + assert.NoError(t, err) + assert.Len(t, methods.Authenticators, 3) + + err = api.User.DeleteAllAuthenticationMethods(user.GetID()) + assert.NoError(t, err) + + methods, err = api.User.GetAuthenticationMethods(user.GetID()) + assert.NoError(t, err) + assert.Len(t, methods.Authenticators, 0) +} + func givenAUser(t *testing.T) *User { t.Helper() diff --git a/test/data/recordings/TestUserManager_AuthenticationMethods.yaml b/test/data/recordings/TestUserManager_AuthenticationMethods.yaml new file mode 100644 index 00000000..8632eeb3 --- /dev/null +++ b/test/data/recordings/TestUserManager_AuthenticationMethods.yaml @@ -0,0 +1,468 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 480 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: | + {"connection":"Username-Password-Authentication","email":"chuck334@example.com","given_name":"Chuck","family_name":"Sanchez","username":"test-user695","nickname":"Chucky","password":"Passwords hide their chuck","user_metadata":{"favourite_attack":"roundhouse_kick"},"verify_email":false,"app_metadata":{"facts":["count_to_infinity_twice","kill_two_stones_with_one_bird","can_hear_sign_language"]},"picture":"https://example-picture-url.jpg","blocked":false,"email_verified":true} + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0-SDK/latest + url: https://go-auth0-dev.eu.auth0.com/api/v2/users + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 661 + uncompressed: false + body: '{"blocked":false,"created_at":"2023-03-10T16:25:50.971Z","email":"chuck334@example.com","email_verified":true,"family_name":"Sanchez","given_name":"Chuck","identities":[{"connection":"Username-Password-Authentication","user_id":"640b5a0ed3534be8b2db9dd3","provider":"auth0","isSocial":false}],"name":"chuck334@example.com","nickname":"Chucky","picture":"https://example-picture-url.jpg","updated_at":"2023-03-10T16:25:50.971Z","user_id":"auth0|640b5a0ed3534be8b2db9dd3","user_metadata":{"favourite_attack":"roundhouse_kick"},"username":"test-user695","app_metadata":{"facts":["count_to_infinity_twice","kill_two_stones_with_one_bird","can_hear_sign_language"]}}' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 201 Created + code: 201 + duration: 5.183459s + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 62 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: | + {"type":"email","name":"Test","email":"chuck334@example.com"} + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0-SDK/latest + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C640b5a0ed3534be8b2db9dd3/authentication-methods + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 135 + uncompressed: false + body: '{"type":"email","name":"Test","created_at":"2023-03-10T16:25:51.113Z","email":"chuc****@exam*******","id":"email|dev_f0O81fTcftc0kN2v"}' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 201 Created + code: 201 + duration: 142.877375ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 5 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: | + null + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0-SDK/latest + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C640b5a0ed3534be8b2db9dd3/authentication-methods?include_totals=true&per_page=50 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: -1 + uncompressed: true + body: '{"authenticators":[{"id":"email|dev_f0O81fTcftc0kN2v","type":"email","confirmed":true,"name":"Test","email":"chuc****@exam*******","created_at":"2023-03-10T16:25:51.113Z"}],"total":1,"start":0,"limit":50}' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 200 OK + code: 200 + duration: 143.365125ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 5 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: | + null + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0-SDK/latest + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C640b5a0ed3534be8b2db9dd3/authentication-methods/email%7Cdev_f0O81fTcftc0kN2v?include_totals=true&per_page=50 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: -1 + uncompressed: true + body: '{"id":"email|dev_f0O81fTcftc0kN2v","type":"email","confirmed":true,"name":"Test","email":"chuc****@exam*******","created_at":"2023-03-10T16:25:51.113Z"}' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 200 OK + code: 200 + duration: 114.130584ms + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 17 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: | + {"name":"Test2"} + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0-SDK/latest + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C640b5a0ed3534be8b2db9dd3/authentication-methods/email%7Cdev_f0O81fTcftc0kN2v + method: PATCH + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: -1 + uncompressed: true + body: '{"type":"email","name":"Test2","created_at":"2023-03-10T16:25:51.113Z","email":"chuc****@exam*******","id":"email|dev_f0O81fTcftc0kN2v"}' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 200 OK + code: 200 + duration: 148.465625ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 5 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: | + null + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0-SDK/latest + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C640b5a0ed3534be8b2db9dd3/authentication-methods/email%7Cdev_f0O81fTcftc0kN2v?include_totals=true&per_page=50 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: -1 + uncompressed: true + body: '{"id":"email|dev_f0O81fTcftc0kN2v","type":"email","confirmed":true,"name":"Test2","email":"chuc****@exam*******","created_at":"2023-03-10T16:25:51.113Z"}' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 200 OK + code: 200 + duration: 127.393375ms + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0-SDK/latest + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C640b5a0ed3534be8b2db9dd3/authentication-methods/email%7Cdev_f0O81fTcftc0kN2v + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Type: + - application/json; charset=utf-8 + status: 204 No Content + code: 204 + duration: 128.642167ms + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 5 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: | + null + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0-SDK/latest + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C640b5a0ed3534be8b2db9dd3/authentication-methods?include_totals=true&per_page=50 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: -1 + uncompressed: true + body: '{"authenticators":[],"start":0,"limit":50}' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 200 OK + code: 200 + duration: 121.738834ms + - id: 8 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 257 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: | + [{"type":"email","name":"MyEmail","email":"foo@example.com"},{"type":"phone","name":"MyPhone","phone_number":"+44207183875044","preferred_authentication_method":"sms"},{"type":"totp","name":"MyTotp","totp_secret":"5HCWXIP2MJNSUBGYVUZFLRB2HWIGXR4SYJQXNBQ"}] + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0-SDK/latest + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C640b5a0ed3534be8b2db9dd3/authentication-methods + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: -1 + uncompressed: true + body: '[{"id":"email|dev_jFUpfLan83lYSMIF","type":"email","name":"MyEmail","email":"foo@example.com","created_at":"2023-03-10T16:25:52.098Z"},{"id":"phone|dev_kXVq4drj3Mw6uCF5","type":"phone","name":"MyPhone","phone_number":"+44207183875044","created_at":"2023-03-10T16:25:52.099Z","preferred_authentication_method":"sms","authentication_methods":[{"id":"sms|dev_kXVq4drj3Mw6uCF5","type":"sms"}]},{"id":"totp|dev_F9T7cy0hM0IgHjwP","type":"totp","name":"MyTotp","created_at":"2023-03-10T16:25:52.099Z"}]' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 200 OK + code: 200 + duration: 200.6885ms + - id: 9 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 5 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: | + null + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0-SDK/latest + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C640b5a0ed3534be8b2db9dd3/authentication-methods?include_totals=true&per_page=50 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: -1 + uncompressed: true + body: '{"authenticators":[{"id":"email|dev_jFUpfLan83lYSMIF","type":"email","confirmed":true,"name":"MyEmail","email":"****@exam*******","created_at":"2023-03-10T16:25:52.098Z"},{"id":"totp|dev_F9T7cy0hM0IgHjwP","type":"totp","confirmed":true,"name":"MyTotp","created_at":"2023-03-10T16:25:52.099Z"},{"id":"phone|dev_kXVq4drj3Mw6uCF5","type":"phone","confirmed":true,"name":"MyPhone","phone_number":"XXXXXXXXXXX5044","created_at":"2023-03-10T16:25:52.099Z","preferred_authentication_method":"sms","authentication_methods":[{"id":"sms|dev_kXVq4drj3Mw6uCF5","type":"sms"}]}],"total":3,"start":0,"limit":50}' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 200 OK + code: 200 + duration: 164.578708ms + - id: 10 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0-SDK/latest + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C640b5a0ed3534be8b2db9dd3/authentication-methods + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Type: + - application/json; charset=utf-8 + status: 204 No Content + code: 204 + duration: 127.700166ms + - id: 11 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 5 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: | + null + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0-SDK/latest + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C640b5a0ed3534be8b2db9dd3/authentication-methods?include_totals=true&per_page=50 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: -1 + uncompressed: true + body: '{"authenticators":[],"start":0,"limit":50}' + headers: + Content-Type: + - application/json; charset=utf-8 + status: 200 OK + code: 200 + duration: 126.350833ms + - id: 12 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: go-auth0-dev.eu.auth0.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - Go-Auth0-SDK/latest + url: https://go-auth0-dev.eu.auth0.com/api/v2/users/auth0%7C640b5a0ed3534be8b2db9dd3 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Type: + - application/json; charset=utf-8 + status: 204 No Content + code: 204 + duration: 186.156333ms