Skip to content

Commit

Permalink
feat(e2e): add passwordless flows and fix bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
aeneasr committed Mar 7, 2022
1 parent 151c8cf commit ef3871b
Show file tree
Hide file tree
Showing 19 changed files with 564 additions and 205 deletions.
6 changes: 3 additions & 3 deletions identity/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func TestManager(t *testing.T) {

t.Run("method=CountActiveMultiFactorCredentials", func(t *testing.T) {
id := identity.NewIdentity(config.DefaultIdentityTraitsSchemaID)
count, err := reg.IdentityManager().CountActiveFirstFactorCredentials(ctx, id)
count, err := reg.IdentityManager().CountActiveMultiFactorCredentials(ctx, id)
require.NoError(t, err)
assert.Equal(t, 0, count)

Expand All @@ -182,7 +182,7 @@ func TestManager(t *testing.T) {
Config: []byte(`{"hashed_password":"$argon2id$v=19$m=32,t=2,p=4$cm94YnRVOW5jZzFzcVE4bQ$MNzk5BtR2vUhrp6qQEjRNw"}`),
}

count, err = reg.IdentityManager().CountActiveFirstFactorCredentials(ctx, id)
count, err = reg.IdentityManager().CountActiveMultiFactorCredentials(ctx, id)
require.NoError(t, err)
assert.Equal(t, 0, count)

Expand All @@ -192,7 +192,7 @@ func TestManager(t *testing.T) {
Config: []byte(`{"credentials":[{"is_passwordless":false}]}`),
}

count, err = reg.IdentityManager().CountActiveFirstFactorCredentials(ctx, id)
count, err = reg.IdentityManager().CountActiveMultiFactorCredentials(ctx, id)
require.NoError(t, err)
assert.Equal(t, 1, count)
})
Expand Down
7 changes: 4 additions & 3 deletions internal/settingshelpers/helpers.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package settingshelpers

import (
"github.com/ory/kratos/driver/config"
"github.com/ory/kratos/internal/testhelpers"
"github.com/ory/kratos/selfservice/flow/settings"
"net/http"
"net/http/httptest"
"net/url"
"testing"

"github.com/ory/kratos/driver/config"
"github.com/ory/kratos/internal/testhelpers"
"github.com/ory/kratos/selfservice/flow/settings"
)

func ExpectValidationError(t *testing.T, ts *httptest.Server, hc *http.Client, conf *config.Config, flow string, values func(url.Values)) string {
Expand Down
4 changes: 2 additions & 2 deletions selfservice/flow/login/hook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,8 @@ func TestLoginExecutor(t *testing.T) {
t.Cleanup(testhelpers.SelfServiceHookConfigReset(t, conf))

useIdentity := &identity.Identity{Credentials: map[identity.CredentialsType]identity.Credentials{
identity.CredentialsTypePassword: {Type: identity.CredentialsTypePassword},
identity.CredentialsTypeTOTP: {Type: identity.CredentialsTypeTOTP},
identity.CredentialsTypePassword: {Type: identity.CredentialsTypePassword, Config: []byte(`{"hashed_password": "$argon2id$v=19$m=32,t=2,p=4$cm94YnRVOW5jZzFzcVE4bQ$MNzk5BtR2vUhrp6qQEjRNw"}`), Identifiers: []string{testhelpers.RandomEmail()}},
identity.CredentialsTypeWebAuthn: {Type: identity.CredentialsTypeWebAuthn, Config: []byte(`{"credentials":[{"is_passwordless":false}]}`), Identifiers: []string{testhelpers.RandomEmail()}},
}}
require.NoError(t, reg.Persister().CreateIdentity(context.Background(), useIdentity))

Expand Down
3 changes: 2 additions & 1 deletion selfservice/hook/session_destroyer.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package hook

import (
"github.com/ory/kratos/selfservice/flow/recovery"
"net/http"

"github.com/ory/kratos/selfservice/flow/recovery"

"github.com/ory/kratos/selfservice/flow/login"
"github.com/ory/kratos/session"
)
Expand Down
5 changes: 3 additions & 2 deletions selfservice/strategy/password/settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/ory/kratos/internal/settingshelpers"
"github.com/ory/kratos/text"
"net/http"
"net/url"
"strings"
"testing"

"github.com/ory/kratos/internal/settingshelpers"
"github.com/ory/kratos/text"

kratos "github.com/ory/kratos-client-go"

"github.com/ory/kratos/corpx"
Expand Down
7 changes: 4 additions & 3 deletions selfservice/strategy/webauthn/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,17 +242,18 @@ func (s *Strategy) loginPasswordless(w http.ResponseWriter, r *http.Request, f *
if len(p.Login) == 0 {
// Reset all nodes to not confuse users.
// This is kinda hacky and will probably need to be updated at some point.
previousNodes := f.UI.Nodes
f.UI.Nodes = node.Nodes{}

// Adds the "Continue" button
f.UI.SetCSRF(s.d.GenerateCSRFToken(r))

if err := s.populateLoginMethod(r, f, i, text.NewInfoSelfServiceLoginContinue(), identity.AuthenticatorAssuranceLevel1); errors.Is(err, ErrNoCredentials) {
f.UI.Nodes = previousNodes
return nil, s.handleLoginError(r, f, schema.NewNoWebAuthnCredentials())
} else if err != nil {
return nil, s.handleLoginError(r, f, err)
}

// Adds the "Continue" button
f.UI.SetCSRF(s.d.GenerateCSRFToken(r))
f.UI.Messages.Add(text.NewInfoLoginWebAuthnPasswordless())
f.UI.SetNode(node.NewInputField("identifier", p.Identifier, node.DefaultGroup, node.InputAttributeTypeHidden, node.WithRequiredInputAttribute))
if err := s.d.LoginFlowPersister().UpdateLoginFlow(r.Context(), f); err != nil {
Expand Down
3 changes: 2 additions & 1 deletion selfservice/strategy/webauthn/settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import (
_ "embed"
"encoding/json"
"fmt"
"github.com/ory/kratos/selfservice/flow"
"net/http"
"net/url"
"testing"
"time"

"github.com/ory/kratos/selfservice/flow"

"github.com/ory/x/snapshotx"

"github.com/ory/kratos/selfservice/strategy/webauthn"
Expand Down
1 change: 1 addition & 0 deletions selfservice/strategy/webauthn/strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package webauthn
import (
"context"
"encoding/json"

"github.com/duo-labs/webauthn/webauthn"

"github.com/pkg/errors"
Expand Down
42 changes: 21 additions & 21 deletions test/e2e/cypress/integration/profiles/email/settings/errors.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {appPrefix, gen, website} from '../../../../helpers'
import {routes as react} from '../../../../helpers/react'
import {routes as express} from '../../../../helpers/express'
import { appPrefix, gen, website } from '../../../../helpers'
import { routes as react } from '../../../../helpers/react'
import { routes as express } from '../../../../helpers/express'

context('Settings failures with email profile', () => {
;[
Expand All @@ -16,7 +16,7 @@ context('Settings failures with email profile', () => {
app: 'react' as 'react',
profile: 'spa'
}
].forEach(({route, profile, app, base}) => {
].forEach(({ route, profile, app, base }) => {
describe(`for app ${app}`, () => {
let email = gen.email()
let password = gen.password()
Expand All @@ -32,12 +32,12 @@ context('Settings failures with email profile', () => {
cy.registerApi({
email: emailSecond,
password: passwordSecond,
fields: {'traits.website': 'https://github.com/ory/kratos'}
fields: { 'traits.website': 'https://github.com/ory/kratos' }
})
cy.registerApi({
email,
password,
fields: {'traits.website': website}
fields: { 'traits.website': website }
})
})

Expand All @@ -47,7 +47,7 @@ context('Settings failures with email profile', () => {
cy.visit(base)
cy.clearAllCookies()

cy.login({email, password, cookieUrl: base})
cy.login({ email, password, cookieUrl: base })
cy.visit(route)
})

Expand Down Expand Up @@ -75,8 +75,8 @@ context('Settings failures with email profile', () => {

cy.reauthWithOtherAccount({
previousUrl: loc.toString(),
expect: {email},
type: {email: emailSecond, password: passwordSecond}
expect: { email },
type: { email: emailSecond, password: passwordSecond }
})

cy.location('pathname').should('contain', '/settings')
Expand All @@ -101,10 +101,10 @@ context('Settings failures with email profile', () => {
cy.get('button[value="profile"]').click()

cy.clearAllCookies()
cy.login({email, password, cookieUrl: base})
cy.login({ email, password, cookieUrl: base })

cy.getSession().should((session) => {
const {identity} = session
const { identity } = session
expect(identity.traits.email).to.equal(email)
})
})
Expand All @@ -117,7 +117,7 @@ context('Settings failures with email profile', () => {
cy.visit(base)

cy.getSession().should((session) => {
const {identity} = session
const { identity } = session
expect(identity.traits.email).to.equal(email)
})
})
Expand All @@ -137,7 +137,7 @@ context('Settings failures with email profile', () => {
cy.expectSettingsSaved()

cy.getSession().should((session) => {
const {identity} = session
const { identity } = session
expect(identity.traits.email).to.equal(email) // this is NOT up(email)
expect(identity.traits.website).to.equal(
'http://github.com/aeneasr'
Expand Down Expand Up @@ -178,8 +178,8 @@ context('Settings failures with email profile', () => {

cy.reauthWithOtherAccount({
previousUrl: loc.toString(),
expect: {email},
type: {email: emailSecond, password: passwordSecond}
expect: { email },
type: { email: emailSecond, password: passwordSecond }
})

cy.location('pathname').should('contain', '/settings')
Expand Down Expand Up @@ -230,7 +230,7 @@ context('Settings failures with email profile', () => {
cy.get('button[value="password"]').click()

cy.clearAllCookies()
cy.login({email, password, cookieUrl: base})
cy.login({ email, password, cookieUrl: base })
cy.clearAllCookies()
cy.login({
email,
Expand All @@ -247,7 +247,7 @@ context('Settings failures with email profile', () => {
cy.register({
email,
password,
fields: {'traits.website': website}
fields: { 'traits.website': website }
})
cy.visit(route)

Expand All @@ -264,14 +264,14 @@ context('Settings failures with email profile', () => {
cy.get('button[value="password"]').click()

cy.location('pathname').should('include', '/login')
cy.reauth({expect: {email}, type: {password: password}})
cy.reauth({ expect: { email }, type: { password: password } })

cy.location('pathname').should('include', '/settings')
cy.get('input[name="password"]').should('exist')

// This should pass because it is the correct password
cy.clearAllCookies()
cy.login({email, password: validPassword, cookieUrl: base})
cy.login({ email, password: validPassword, cookieUrl: base })

// This should fail because it is the wrong password
cy.clearAllCookies()
Expand All @@ -295,13 +295,13 @@ context('Settings failures with email profile', () => {
describe('global errors', () => {
it('fails when CSRF is incorrect', () => {
cy.get(appPrefix(app) + 'input[name="password"]').type('12345678')
cy.shouldHaveCsrfError({app})
cy.shouldHaveCsrfError({ app })
})

it('fails when a disallowed return_to url is requested', () => {
cy.shouldErrorOnDisallowedReturnTo(
route + '?return_to=https://not-allowed',
{app}
{ app }
)
})
})
Expand Down
22 changes: 4 additions & 18 deletions test/e2e/cypress/integration/profiles/mfa/mix.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,7 @@ context('2FA with various methods', () => {
}).then(() => {
cy.getSession({
expectAal: 'aal1',
expectMethods: [
'password'
]
expectMethods: ['password']
})

cy.visit(settings)
Expand All @@ -92,10 +90,7 @@ context('2FA with various methods', () => {
cy.expectSettingsSaved()
cy.getSession({
expectAal: 'aal2',
expectMethods: [
'password',
'totp'
]
expectMethods: ['password', 'totp']
})

// Set up lookup secrets
Expand All @@ -109,11 +104,7 @@ context('2FA with various methods', () => {
cy.expectSettingsSaved()
cy.getSession({
expectAal: 'aal2',
expectMethods: [
'password',
'totp',
'lookup_secret'
]
expectMethods: ['password', 'totp', 'lookup_secret']
})

// Set up WebAuthn
Expand All @@ -124,12 +115,7 @@ context('2FA with various methods', () => {
cy.expectSettingsSaved()
cy.getSession({
expectAal: 'aal2',
expectMethods: [
'password',
'totp',
'webauthn',
'lookup_secret'
]
expectMethods: ['password', 'totp', 'webauthn', 'lookup_secret']
})

cy.visit(login + '?aal=aal2&refresh=true')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('Registration failures with email profile', () => {
it('should not be able to verify because post webhook uses local jsonnet', () => {
cy.setDefaultIdentitySchema('working')
cy.visit(express.registration, { failOnStatusCode: false })
cy.get('[data-testid="node/input/traits.email"] input').type('[email protected]')
cy.get('[data-testid="node/input/traits.email"] input').type(gen.email())
cy.get('[data-testid="node/input/traits.website"] input').type(
'https://google.com/'
)
Expand Down
Loading

0 comments on commit ef3871b

Please sign in to comment.