Skip to content

Commit ee0738f

Browse files
committed
chore: add cypress tests
1 parent df22c9e commit ee0738f

File tree

6 files changed

+945
-872
lines changed

6 files changed

+945
-872
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// Copyright © 2022 Ory Corp
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { prng } from "../../helpers"
5+
6+
const accessTokenStrategies = ["opaque", "jwt"]
7+
8+
describe("The OAuth 2.0 Device Authorization Grant", function () {
9+
accessTokenStrategies.forEach((accessTokenStrategy) => {
10+
describe("access_token_strategy=" + accessTokenStrategy, function () {
11+
const nc = (extradata) => ({
12+
client_secret: prng(),
13+
scope: "offline_access openid",
14+
subject_type: "public",
15+
token_endpoint_auth_method: "client_secret_basic",
16+
grant_types: [
17+
"urn:ietf:params:oauth:grant-type:device_code",
18+
"refresh_token",
19+
],
20+
access_token_strategy: accessTokenStrategy,
21+
...extradata,
22+
})
23+
24+
it("should return an Access, Refresh, and ID Token when scope offline_access and openid are granted", function () {
25+
const client = nc()
26+
cy.deviceAuthFlow(client, {
27+
consent: { scope: ["offline_access", "openid"] },
28+
})
29+
30+
cy.postDeviceAuthFlow().then((resp) => {
31+
const {
32+
result,
33+
token: { access_token, id_token, refresh_token },
34+
} = resp.body
35+
36+
expect(result).to.equal("success")
37+
expect(access_token).to.not.be.empty
38+
expect(id_token).to.not.be.empty
39+
expect(refresh_token).to.not.be.empty
40+
})
41+
})
42+
43+
it("should return an Access and Refresh Token when scope offline_access is granted", function () {
44+
const client = nc()
45+
cy.deviceAuthFlow(client, { consent: { scope: ["offline_access"] } })
46+
47+
cy.postDeviceAuthFlow().then((resp) => {
48+
console.log(resp)
49+
const {
50+
result,
51+
token: { access_token, id_token, refresh_token },
52+
} = resp.body
53+
54+
expect(result).to.equal("success")
55+
expect(access_token).to.not.be.empty
56+
expect(id_token).to.be.undefined
57+
expect(refresh_token).to.not.be.empty
58+
})
59+
})
60+
61+
it("should return an Access and ID Token when scope offline_access is granted", function () {
62+
const client = nc()
63+
cy.deviceAuthFlow(client, { consent: { scope: ["openid"] } })
64+
65+
cy.postDeviceAuthFlow().then((resp) => {
66+
console.log(resp)
67+
const {
68+
result,
69+
token: { access_token, id_token, refresh_token },
70+
} = resp.body
71+
72+
expect(result).to.equal("success")
73+
expect(access_token).to.not.be.empty
74+
expect(id_token).to.not.be.empty
75+
expect(refresh_token).to.be.undefined
76+
})
77+
})
78+
79+
it("should return an Access Token when no scope is granted", function () {
80+
const client = nc()
81+
cy.deviceAuthFlow(client, { consent: { scope: [] } })
82+
83+
cy.postDeviceAuthFlow().then((resp) => {
84+
console.log(resp)
85+
const {
86+
result,
87+
token: { access_token, id_token, refresh_token },
88+
} = resp.body
89+
90+
expect(result).to.equal("success")
91+
expect(access_token).to.not.be.empty
92+
expect(id_token).to.be.undefined
93+
expect(refresh_token).to.be.undefined
94+
})
95+
})
96+
97+
it("should skip consent if the client is confgured thus", function () {
98+
const client = nc({ skip_consent: true })
99+
cy.deviceAuthFlow(client, {
100+
consent: { scope: ["offline_access", "openid"], skip: true },
101+
})
102+
103+
cy.postDeviceAuthFlow().then((resp) => {
104+
console.log(resp)
105+
const {
106+
result,
107+
token: { access_token, id_token, refresh_token },
108+
} = resp.body
109+
110+
expect(result).to.equal("success")
111+
expect(access_token).to.not.be.empty
112+
expect(id_token).to.not.be.empty
113+
expect(refresh_token).to.not.be.empty
114+
})
115+
})
116+
})
117+
})
118+
})

cypress/support/commands.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,90 @@ Cypress.Commands.add("refreshTokenBrowser", (client, token) =>
216216
failOnStatusCode: false,
217217
}),
218218
)
219+
220+
Cypress.Commands.add(
221+
"deviceAuthFlow",
222+
(
223+
client,
224+
{
225+
override: { scope, client_id, client_secret } = {},
226+
consent: {
227+
accept: acceptConsent = true,
228+
skip: skipConsent = false,
229+
remember: rememberConsent = false,
230+
scope: acceptScope = [],
231+
} = {},
232+
login: {
233+
accept: acceptLogin = true,
234+
skip: skipLogin = false,
235+
remember: rememberLogin = false,
236+
username = "foo@bar.com",
237+
password = "foobar",
238+
} = {},
239+
prompt = "",
240+
createClient: doCreateClient = true,
241+
} = {},
242+
path = "oauth2",
243+
) => {
244+
const run = (client) => {
245+
cy.visit(
246+
`${Cypress.env("client_url")}/${path}/device?client_id=${
247+
client_id || client.client_id
248+
}&client_secret=${client_secret || client.client_secret}&scope=${
249+
scope || client.scope
250+
}`,
251+
{ failOnStatusCode: false },
252+
)
253+
254+
cy.get("#verify").click()
255+
256+
if (!skipLogin) {
257+
cy.get("#email").type(username, { delay: 1 })
258+
cy.get("#password").type(password, { delay: 1 })
259+
260+
if (rememberLogin) {
261+
cy.get("#remember").click()
262+
}
263+
264+
if (acceptLogin) {
265+
cy.get("#accept").click()
266+
} else {
267+
cy.get("#reject").click()
268+
}
269+
}
270+
271+
if (!skipConsent) {
272+
acceptScope.forEach((s) => {
273+
cy.get(`#${s}`).click()
274+
})
275+
276+
if (rememberConsent) {
277+
cy.get("#remember").click()
278+
}
279+
280+
if (acceptConsent) {
281+
cy.get("#accept").click()
282+
} else {
283+
cy.get("#reject").click()
284+
}
285+
286+
cy.location().should((loc) => {
287+
expect(loc.origin).to.eq(Cypress.env("consent_url"))
288+
expect(loc.pathname).to.eq("/oauth2/device/success")
289+
})
290+
}
291+
}
292+
293+
if (doCreateClient) {
294+
createClient(client).should((client) => {
295+
run(client)
296+
})
297+
return
298+
}
299+
run(client)
300+
},
301+
)
302+
303+
Cypress.Commands.add("postDeviceAuthFlow", (path = "oauth2") =>
304+
cy.request(`${Cypress.env("client_url")}/${path}/device/success`),
305+
)

test/e2e/circle-ci.bash

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ fi
3838
(cd oauth2-client; PORT=5002 HYDRA_ADMIN_URL=http://127.0.0.1:5001 npm run consent > ../login-consent-logout.e2e.log 2>&1 &)
3939

4040
export URLS_SELF_ISSUER=http://127.0.0.1:5004/
41+
export URLS_DEVICE_VERIFICATION=http://127.0.0.1:5002/device/verify
42+
export URLS_DEVICE_SUCCESS=http://127.0.0.1:5002/oauth2/device/success
4143
export URLS_CONSENT=http://127.0.0.1:5002/consent
4244
export URLS_LOGIN=http://127.0.0.1:5002/login
4345
export URLS_LOGOUT=http://127.0.0.1:5002/logout

0 commit comments

Comments
 (0)