Skip to content

Commit

Permalink
fix(selfservice): Cannot login after remove security keys and all oth…
Browse files Browse the repository at this point in the history
…er 2FA settings (#2181)

Closes #2180

Signed-off-by: sawadashota <[email protected]>
  • Loading branch information
sawadashota authored Jan 31, 2022
1 parent 9421fbc commit 5ff6773
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 3 deletions.
8 changes: 7 additions & 1 deletion selfservice/strategy/webauthn/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,18 @@ import (
"github.com/tidwall/sjson"

"github.com/ory/herodot"

"github.com/ory/kratos/session"

"github.com/gofrs/uuid"
"github.com/pkg/errors"

"github.com/ory/x/decoderx"

"github.com/ory/kratos/identity"
"github.com/ory/kratos/selfservice/flow"
"github.com/ory/kratos/selfservice/flow/settings"
"github.com/ory/kratos/x"
"github.com/ory/x/decoderx"
)

func (s *Strategy) RegisterSettingsRoutes(_ *x.RouterPublic) {
Expand Down Expand Up @@ -188,6 +190,10 @@ func (s *Strategy) continueSettingsFlowRemove(w http.ResponseWriter, r *http.Req
if len(updated) == len(cc.Credentials) {
return errors.WithStack(herodot.ErrBadRequest.WithReasonf("You tried to remove a WebAuthn credential which does not exist."))
}
if len(updated) == 0 {
i.DeleteCredentialsType(identity.CredentialsTypeWebAuthn)
return nil
}

cc.Credentials = updated
cred.Config, err = json.Marshal(cc)
Expand Down
43 changes: 41 additions & 2 deletions selfservice/strategy/webauthn/settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ import (

"github.com/stretchr/testify/require"

"github.com/ory/x/assertx"
"github.com/ory/x/sqlxx"

"github.com/ory/kratos/driver"
"github.com/ory/kratos/driver/config"
"github.com/ory/kratos/identity"
"github.com/ory/kratos/internal"
"github.com/ory/kratos/internal/testhelpers"
"github.com/ory/kratos/x"
"github.com/ory/x/assertx"
"github.com/ory/x/sqlxx"
)

//go:embed fixtures/settings/has_webauth.json
Expand Down Expand Up @@ -347,6 +348,44 @@ func TestCompleteSettings(t *testing.T) {
})
})

t.Run("case=remove all security keys", func(t *testing.T) {
run := func(t *testing.T, spa bool) {
id := createIdentity(t, reg)
allCred, ok := id.GetCredentials(identity.CredentialsTypeWebAuthn)
assert.True(t, ok)

var cc webauthn.CredentialsConfig
require.NoError(t, json.Unmarshal(allCred.Config, &cc))
require.Len(t, cc.Credentials, 2)

for _, cred := range cc.Credentials {
body, res := doBrowserFlow(t, spa, func(v url.Values) {
v.Set(node.WebAuthnRemove, fmt.Sprintf("%x", cred.ID))
}, id)

if spa {
assert.Contains(t, res.Request.URL.String(), publicTS.URL+settings.RouteSubmitFlow)
} else {
assert.Contains(t, res.Request.URL.String(), uiTS.URL)
}
assert.EqualValues(t, settings.StateSuccess, gjson.Get(body, "state").String(), body)
}

actual, err := reg.Persister().GetIdentityConfidential(context.Background(), id.ID)
require.NoError(t, err)
_, ok = actual.GetCredentials(identity.CredentialsTypeWebAuthn)
assert.False(t, ok)
}

t.Run("type=browser", func(t *testing.T) {
run(t, false)
})

t.Run("type=spa", func(t *testing.T) {
run(t, true)
})
})

t.Run("case=fails with browser submit register payload is invalid", func(t *testing.T) {
run := func(t *testing.T, spa bool) {
id := createIdentity(t, reg)
Expand Down

0 comments on commit 5ff6773

Please sign in to comment.