snapshot of https://github.com/ory/kratos.git (master, 2026-09-15; blobs > 131072B omitted)
Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
This commit is contained in:
166
test/e2e/cypress/integration/profiles/oidc-provider/mfa.spec.ts
Normal file
166
test/e2e/cypress/integration/profiles/oidc-provider/mfa.spec.ts
Normal file
@@ -0,0 +1,166 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { gen } from "../../../helpers"
|
||||
import { routes as express } from "../../../helpers/express"
|
||||
import * as oauth2 from "../../../helpers/oauth2"
|
||||
import * as httpbin from "../../../helpers/httpbin"
|
||||
import { TOTP } from "otpauth"
|
||||
|
||||
context("OIDC Provider 2FA", () => {
|
||||
const client = {
|
||||
auth_endpoint: "http://localhost:4744/oauth2/auth",
|
||||
token_endpoint: "http://localhost:4744/oauth2/token",
|
||||
id: Cypress.env("OIDC_DUMMY_CLIENT_ID"),
|
||||
secret: Cypress.env("OIDC_DUMMY_CLIENT_SECRET"),
|
||||
token_endpoint_auth_method: "client_secret_basic",
|
||||
grant_types: ["authorization_code", "refresh_token"],
|
||||
response_types: ["code", "id_token"],
|
||||
scopes: ["openid", "offline", "email", "website"],
|
||||
callbacks: [
|
||||
"http://localhost:5555/callback",
|
||||
"https://ory-network-httpbin-ijakee5waq-ez.a.run.app/anything",
|
||||
],
|
||||
}
|
||||
|
||||
;[
|
||||
{
|
||||
login: express.login,
|
||||
settings: express.settings,
|
||||
base: express.base,
|
||||
profile: "oidc-provider-mfa",
|
||||
app: "express" as "express",
|
||||
},
|
||||
].forEach(({ settings, login, profile, app, base }) => {
|
||||
describe(`for app ${app}`, () => {
|
||||
let email = gen.email()
|
||||
let password = gen.password()
|
||||
let secret
|
||||
|
||||
before(() => {
|
||||
cy.useConfigProfile(profile)
|
||||
cy.proxy(app)
|
||||
|
||||
email = gen.email()
|
||||
password = gen.password()
|
||||
|
||||
cy.register({
|
||||
email,
|
||||
password,
|
||||
fields: { "traits.website": "http://t1.local" },
|
||||
})
|
||||
cy.visit(settings)
|
||||
|
||||
cy.get('[data-testid="node/text/totp_secret_key/text"]').then(($e) => {
|
||||
secret = $e.text().trim()
|
||||
})
|
||||
cy.get('input[name="totp_code"]').then(($e) => {
|
||||
cy.wrap($e).type(
|
||||
new TOTP({
|
||||
secret,
|
||||
}).generate(),
|
||||
)
|
||||
})
|
||||
cy.get('*[name="method"][value="totp"]').click()
|
||||
cy.expectSettingsSaved()
|
||||
cy.getSession({
|
||||
expectAal: "aal2",
|
||||
expectMethods: ["password", "totp"],
|
||||
})
|
||||
|
||||
cy.clearAllCookies()
|
||||
})
|
||||
|
||||
it("should be be asked to sign in with 2fa if set up", () => {
|
||||
let url = oauth2.getDefaultAuthorizeURL(client)
|
||||
|
||||
cy.get("body")
|
||||
.then((body$) => {
|
||||
// Credits https://github.com/suchipi, https://github.com/cypress-io/cypress/issues/944#issuecomment-444312914
|
||||
const appWindow = body$[0].ownerDocument.defaultView
|
||||
const appIframe = appWindow.parent.document.querySelector("iframe")
|
||||
|
||||
return new Promise((resolve) => {
|
||||
appIframe.onload = () => resolve(undefined)
|
||||
appWindow.location.href = url
|
||||
})
|
||||
})
|
||||
.then(() => {
|
||||
// kratos login ui
|
||||
cy.get("[name=identifier]").type(email)
|
||||
cy.get("[name=password]").type(password)
|
||||
cy.get("[type=submit]").click()
|
||||
|
||||
cy.get('input[name="totp_code"]').then(($e) => {
|
||||
cy.wrap($e).type(
|
||||
new TOTP({
|
||||
secret,
|
||||
}).generate(),
|
||||
)
|
||||
})
|
||||
cy.get('*[name="method"][value="totp"]').click()
|
||||
|
||||
// consent ui
|
||||
cy.get("#openid").click()
|
||||
cy.get("#offline").click()
|
||||
cy.get("#accept").click()
|
||||
|
||||
let scope = ["offline", "openid"]
|
||||
httpbin.checkToken(client, scope, (token: any) => {
|
||||
expect(token).to.have.property("access_token")
|
||||
expect(token).to.have.property("id_token")
|
||||
expect(token).to.have.property("refresh_token")
|
||||
expect(token).to.have.property("token_type")
|
||||
expect(token).to.have.property("expires_in")
|
||||
expect(token.scope).to.equal("offline openid")
|
||||
let idToken = JSON.parse(
|
||||
decodeURIComponent(
|
||||
escape(window.atob(token.id_token.split(".")[1])),
|
||||
),
|
||||
)
|
||||
expect(idToken).to.have.property("amr")
|
||||
expect(idToken.amr).to.deep.equal(["password", "totp"])
|
||||
})
|
||||
|
||||
// We shouldn't need to authenticate again
|
||||
url = oauth2.getDefaultAuthorizeURL(client)
|
||||
|
||||
cy.get("body")
|
||||
.then((body$) => {
|
||||
// Credits https://github.com/suchipi, https://github.com/cypress-io/cypress/issues/944#issuecomment-444312914
|
||||
const appWindow = body$[0].ownerDocument.defaultView
|
||||
const appIframe =
|
||||
appWindow.parent.document.querySelector("iframe")
|
||||
|
||||
return new Promise((resolve) => {
|
||||
appIframe.onload = () => resolve(undefined)
|
||||
appWindow.location.href = url
|
||||
})
|
||||
})
|
||||
.then(() => {
|
||||
// We get the consent screen instead of login
|
||||
cy.get("#openid").click()
|
||||
cy.get("#offline").click()
|
||||
cy.get("#accept").click()
|
||||
|
||||
httpbin.checkToken(client, scope, (token: any) => {
|
||||
expect(token).to.have.property("access_token")
|
||||
expect(token).to.have.property("id_token")
|
||||
expect(token).to.have.property("refresh_token")
|
||||
expect(token).to.have.property("token_type")
|
||||
expect(token).to.have.property("expires_in")
|
||||
expect(token.scope).to.equal("offline openid")
|
||||
let idToken = JSON.parse(
|
||||
decodeURIComponent(
|
||||
escape(window.atob(token.id_token.split(".")[1])),
|
||||
),
|
||||
)
|
||||
expect(idToken).to.have.property("amr")
|
||||
expect(idToken.amr).to.deep.equal(["password", "totp"])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user