Skip to content

Commit

Permalink
Adding TotpInfo to userRecord
Browse files Browse the repository at this point in the history
  • Loading branch information
pragatimodi committed May 31, 2023
1 parent 61c6c04 commit 3f140e0
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 69 deletions.
76 changes: 51 additions & 25 deletions auth/user_mgt.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const (
createUserMethod = "createUser"
updateUserMethod = "updateUser"
phoneMultiFactorID = "phone"
totpMultiFactorID = "totp"
)

// 'REDACTED', encoded as a base64 string.
Expand All @@ -62,20 +63,29 @@ type UserInfo struct {

// multiFactorInfoResponse describes the `mfaInfo` of the user record API response
type multiFactorInfoResponse struct {
MFAEnrollmentID string `json:"mfaEnrollmentId,omitempty"`
DisplayName string `json:"displayName,omitempty"`
PhoneInfo string `json:"phoneInfo,omitempty"`
EnrolledAt string `json:"enrolledAt,omitempty"`
MFAEnrollmentID string `json:"mfaEnrollmentId,omitempty"`
DisplayName string `json:"displayName,omitempty"`
PhoneInfo string `json:"phoneInfo,omitempty"`
TOTPInfo *TOTPInfo `json:"totpInfo,omitempty"`
EnrolledAt string `json:"enrolledAt,omitempty"`
}

// TOTPInfo describes a user enrolled second totp factor.
type TOTPInfo struct{}

// PhoneMultiFactorInfo describes a user enrolled second phone factor.
type PhoneMultiFactorInfo struct {
PhoneNumber string
}

// MultiFactorInfo describes a user enrolled second phone factor.
// TODO : convert PhoneNumber to PhoneMultiFactorInfo struct
type MultiFactorInfo struct {
UID string
DisplayName string
EnrollmentTimestamp int64
FactorID string
PhoneNumber string
UID string
DisplayName string
EnrollmentTimestamp int64
FactorID string
PhoneMultiFactorInfo *PhoneMultiFactorInfo
TOTPMultiFactorInfo *TOTPInfo
}

// MultiFactorSettings describes the multi-factor related user settings.
Expand Down Expand Up @@ -170,12 +180,18 @@ func convertMultiFactorInfoToServerFormat(mfaInfo MultiFactorInfo) (multiFactorI
if mfaInfo.EnrollmentTimestamp != 0 {
authFactorInfo.EnrolledAt = time.Unix(mfaInfo.EnrollmentTimestamp, 0).Format("2006-01-02T15:04:05Z07:00Z")
}
if mfaInfo.FactorID == phoneMultiFactorID {
authFactorInfo.PhoneInfo = mfaInfo.PhoneNumber
authFactorInfo.DisplayName = mfaInfo.DisplayName
authFactorInfo.MFAEnrollmentID = mfaInfo.UID
authFactorInfo.DisplayName = mfaInfo.DisplayName
authFactorInfo.MFAEnrollmentID = mfaInfo.UID

switch mfaInfo.FactorID {
case phoneMultiFactorID:
authFactorInfo.PhoneInfo = mfaInfo.PhoneMultiFactorInfo.PhoneNumber
return authFactorInfo, nil
case totpMultiFactorID:
authFactorInfo.TOTPInfo = (*TOTPInfo)(mfaInfo.TOTPMultiFactorInfo)
return authFactorInfo, nil
}

out, _ := json.Marshal(mfaInfo)
return multiFactorInfoResponse{}, fmt.Errorf("Unsupported second factor %s provided", string(out))
}
Expand Down Expand Up @@ -675,8 +691,8 @@ func validateAndFormatMfaSettings(mfaSettings MultiFactorSettings, methodType st
return nil, fmt.Errorf("the second factor \"displayName\" for \"%s\" must be a valid non-empty string", multiFactorInfo.DisplayName)
}
if multiFactorInfo.FactorID == phoneMultiFactorID {
if err := validatePhone(multiFactorInfo.PhoneNumber); err != nil {
return nil, fmt.Errorf("the second factor \"phoneNumber\" for \"%s\" must be a non-empty E.164 standard compliant identifier string", multiFactorInfo.PhoneNumber)
if err := validatePhone(multiFactorInfo.PhoneMultiFactorInfo.PhoneNumber); err != nil {
return nil, fmt.Errorf("the second factor \"phoneNumber\" for \"%s\" must be a non-empty E.164 standard compliant identifier string", multiFactorInfo.PhoneMultiFactorInfo.PhoneNumber)
}
}
obj, err := convertMultiFactorInfoToServerFormat(*multiFactorInfo)
Expand Down Expand Up @@ -1075,17 +1091,27 @@ func (r *userQueryResponse) makeExportedUserRecord() (*ExportedUserRecord, error
enrollmentTimestamp = t.Unix() * 1000
}

if factor.PhoneInfo == "" {
if factor.PhoneInfo != "" {
enrolledFactors = append(enrolledFactors, &MultiFactorInfo{
UID: factor.MFAEnrollmentID,
DisplayName: factor.DisplayName,
EnrollmentTimestamp: enrollmentTimestamp,
FactorID: phoneMultiFactorID,
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: factor.PhoneInfo,
},
})
} else if factor.TOTPInfo != nil {
enrolledFactors = append(enrolledFactors, &MultiFactorInfo{
UID: factor.MFAEnrollmentID,
DisplayName: factor.DisplayName,
EnrollmentTimestamp: enrollmentTimestamp,
FactorID: totpMultiFactorID,
TOTPMultiFactorInfo: &TOTPInfo{},
})
} else {
return nil, fmt.Errorf("unsupported multi-factor auth response: %#v", factor)
}

enrolledFactors = append(enrolledFactors, &MultiFactorInfo{
UID: factor.MFAEnrollmentID,
DisplayName: factor.DisplayName,
EnrollmentTimestamp: enrollmentTimestamp,
FactorID: phoneMultiFactorID,
PhoneNumber: factor.PhoneInfo,
})
}

return &ExportedUserRecord{
Expand Down
89 changes: 65 additions & 24 deletions auth/user_mgt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,20 @@ var testUser = &UserRecord{
MultiFactor: &MultiFactorSettings{
EnrolledFactors: []*MultiFactorInfo{
{
UID: "0aaded3f-5e73-461d-aef9-37b48e3769be",
UID: "enrolledFactor1",
FactorID: "phone",
EnrollmentTimestamp: 1614776780000,
PhoneNumber: "+1234567890",
DisplayName: "My MFA Phone",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "+1234567890",
},
DisplayName: "My MFA Phone",
},
{
UID: "enrolledFactor2",
FactorID: "totp",
EnrollmentTimestamp: 1614776780000,
TOTPMultiFactorInfo: &TOTPInfo{},
DisplayName: "My MFA TOTP",
},
},
},
Expand Down Expand Up @@ -646,8 +655,10 @@ func TestInvalidCreateUser(t *testing.T) {
(&UserToCreate{}).MFASettings(MultiFactorSettings{
EnrolledFactors: []*MultiFactorInfo{
{
UID: "EnrollmentID",
PhoneNumber: "+11234567890",
UID: "EnrollmentID",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "+11234567890",
},
DisplayName: "Spouse's phone number",
FactorID: "phone",
},
Expand All @@ -658,7 +669,9 @@ func TestInvalidCreateUser(t *testing.T) {
(&UserToCreate{}).MFASettings(MultiFactorSettings{
EnrolledFactors: []*MultiFactorInfo{
{
PhoneNumber: "invalid",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "invalid",
},
DisplayName: "Spouse's phone number",
FactorID: "phone",
},
Expand All @@ -669,7 +682,9 @@ func TestInvalidCreateUser(t *testing.T) {
(&UserToCreate{}).MFASettings(MultiFactorSettings{
EnrolledFactors: []*MultiFactorInfo{
{
PhoneNumber: "+11234567890",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "+11234567890",
},
DisplayName: "Spouse's phone number",
FactorID: "phone",
EnrollmentTimestamp: time.Now().UTC().Unix(),
Expand All @@ -681,7 +696,9 @@ func TestInvalidCreateUser(t *testing.T) {
(&UserToCreate{}).MFASettings(MultiFactorSettings{
EnrolledFactors: []*MultiFactorInfo{
{
PhoneNumber: "+11234567890",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "+11234567890",
},
DisplayName: "Spouse's phone number",
FactorID: "",
},
Expand All @@ -692,8 +709,10 @@ func TestInvalidCreateUser(t *testing.T) {
(&UserToCreate{}).MFASettings(MultiFactorSettings{
EnrolledFactors: []*MultiFactorInfo{
{
PhoneNumber: "+11234567890",
FactorID: "phone",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "+11234567890",
},
FactorID: "phone",
},
},
}),
Expand Down Expand Up @@ -773,7 +792,9 @@ var createUserCases = []struct {
(&UserToCreate{}).MFASettings(MultiFactorSettings{
EnrolledFactors: []*MultiFactorInfo{
{
PhoneNumber: "+11234567890",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "+11234567890",
},
DisplayName: "Spouse's phone number",
FactorID: "phone",
},
Expand All @@ -790,12 +811,16 @@ var createUserCases = []struct {
(&UserToCreate{}).MFASettings(MultiFactorSettings{
EnrolledFactors: []*MultiFactorInfo{
{
PhoneNumber: "+11234567890",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "+11234567890",
},
DisplayName: "number1",
FactorID: "phone",
},
{
PhoneNumber: "+11234567890",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "+11234567890",
},
DisplayName: "number2",
FactorID: "phone",
},
Expand Down Expand Up @@ -875,9 +900,11 @@ func TestInvalidUpdateUser(t *testing.T) {
(&UserToUpdate{}).MFASettings(MultiFactorSettings{
EnrolledFactors: []*MultiFactorInfo{
{
UID: "enrolledSecondFactor1",
PhoneNumber: "+11234567890",
FactorID: "phone",
UID: "enrolledSecondFactor1",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "+11234567890",
},
FactorID: "phone",
},
},
}),
Expand All @@ -886,8 +913,10 @@ func TestInvalidUpdateUser(t *testing.T) {
(&UserToUpdate{}).MFASettings(MultiFactorSettings{
EnrolledFactors: []*MultiFactorInfo{
{
UID: "enrolledSecondFactor1",
PhoneNumber: "invalid",
UID: "enrolledSecondFactor1",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "invalid",
},
DisplayName: "Spouse's phone number",
FactorID: "phone",
},
Expand All @@ -898,7 +927,9 @@ func TestInvalidUpdateUser(t *testing.T) {
(&UserToUpdate{}).MFASettings(MultiFactorSettings{
EnrolledFactors: []*MultiFactorInfo{
{
PhoneNumber: "+11234567890",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "+11234567890",
},
FactorID: "phone",
DisplayName: "Spouse's phone number",
},
Expand Down Expand Up @@ -1049,14 +1080,18 @@ var updateUserCases = []struct {
(&UserToUpdate{}).MFASettings(MultiFactorSettings{
EnrolledFactors: []*MultiFactorInfo{
{
UID: "enrolledSecondFactor1",
PhoneNumber: "+11234567890",
UID: "enrolledSecondFactor1",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "+11234567890",
},
DisplayName: "Spouse's phone number",
FactorID: "phone",
EnrollmentTimestamp: time.Now().Unix(),
}, {
UID: "enrolledSecondFactor2",
PhoneNumber: "+11234567890",
UID: "enrolledSecondFactor2",
PhoneMultiFactorInfo: &PhoneMultiFactorInfo{
PhoneNumber: "+11234567890",
},
DisplayName: "Spouse's phone number",
FactorID: "phone",
},
Expand Down Expand Up @@ -1886,10 +1921,16 @@ func TestMakeExportedUser(t *testing.T) {
MFAInfo: []*multiFactorInfoResponse{
{
PhoneInfo: "+1234567890",
MFAEnrollmentID: "0aaded3f-5e73-461d-aef9-37b48e3769be",
MFAEnrollmentID: "enrolledFactor1",
DisplayName: "My MFA Phone",
EnrolledAt: "2021-03-03T13:06:20.542896Z",
},
{
TOTPInfo: &TOTPInfo{},
MFAEnrollmentID: "enrolledFactor2",
DisplayName: "My MFA TOTP",
EnrolledAt: "2021-03-03T13:06:20.542896Z",
},
},
}

Expand Down
14 changes: 9 additions & 5 deletions integration/auth/user_mgt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,9 @@ func TestCreateUserMFA(t *testing.T) {
tc.MFASettings(auth.MultiFactorSettings{
EnrolledFactors: []*auth.MultiFactorInfo{
{
PhoneNumber: "+11234567890",
PhoneMultiFactorInfo: &auth.PhoneMultiFactorInfo{
PhoneNumber: "+11234567890",
},
DisplayName: "Spouse's phone number",
FactorID: "phone",
},
Expand All @@ -447,10 +449,12 @@ func TestCreateUserMFA(t *testing.T) {
defer deleteUser(user.UID)
var factor []*auth.MultiFactorInfo = []*auth.MultiFactorInfo{
{
UID: user.MultiFactor.EnrolledFactors[0].UID,
DisplayName: "Spouse's phone number",
FactorID: "phone",
PhoneNumber: "+11234567890",
UID: user.MultiFactor.EnrolledFactors[0].UID,
DisplayName: "Spouse's phone number",
FactorID: "phone",
PhoneMultiFactorInfo: &auth.PhoneMultiFactorInfo{
PhoneNumber: "+11234567890",
},
EnrollmentTimestamp: user.MultiFactor.EnrolledFactors[0].EnrollmentTimestamp,
},
}
Expand Down
10 changes: 8 additions & 2 deletions testdata/get_user.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,17 @@
"mfaInfo": [
{
"phoneInfo": "+1234567890",
"mfaEnrollmentId": "0aaded3f-5e73-461d-aef9-37b48e3769be",
"mfaEnrollmentId": "enrolledFactor1",
"displayName": "My MFA Phone",
"enrolledAt": "2021-03-03T13:06:20.542896Z"
},
{
"totpInfo": {},
"mfaEnrollmentId": "enrolledFactor2",
"displayName": "My MFA TOTP",
"enrolledAt": "2021-03-03T13:06:20.542896Z"
}
]
}
]
}
}
Loading

0 comments on commit 3f140e0

Please sign in to comment.