* create `features` folder * add base oauth2 server * continue implementing OAuth tests * WIP * add password flow tests * modify Password flow credential types * remove query string credential type * add test case for Authorization flow * add specific Authorization value for Password flow test * WIP * fix linter issuesbubble
@@ -2341,28 +2341,49 @@ | |||
"dev": true | |||
}, | |||
"body-parser": { | |||
"version": "1.18.2", | |||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", | |||
"integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", | |||
"version": "1.18.3", | |||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", | |||
"integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", | |||
"dev": true, | |||
"requires": { | |||
"bytes": "3.0.0", | |||
"content-type": "~1.0.4", | |||
"debug": "2.6.9", | |||
"depd": "~1.1.1", | |||
"http-errors": "~1.6.2", | |||
"iconv-lite": "0.4.19", | |||
"depd": "~1.1.2", | |||
"http-errors": "~1.6.3", | |||
"iconv-lite": "0.4.23", | |||
"on-finished": "~2.3.0", | |||
"qs": "6.5.1", | |||
"raw-body": "2.3.2", | |||
"type-is": "~1.6.15" | |||
"qs": "6.5.2", | |||
"raw-body": "2.3.3", | |||
"type-is": "~1.6.16" | |||
}, | |||
"dependencies": { | |||
"iconv-lite": { | |||
"version": "0.4.19", | |||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", | |||
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", | |||
"version": "0.4.23", | |||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", | |||
"integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", | |||
"dev": true, | |||
"requires": { | |||
"safer-buffer": ">= 2.1.2 < 3" | |||
} | |||
}, | |||
"qs": { | |||
"version": "6.5.2", | |||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", | |||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", | |||
"dev": true | |||
}, | |||
"raw-body": { | |||
"version": "2.3.3", | |||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", | |||
"integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", | |||
"dev": true, | |||
"requires": { | |||
"bytes": "3.0.0", | |||
"http-errors": "1.6.3", | |||
"iconv-lite": "0.4.23", | |||
"unpipe": "1.0.0" | |||
} | |||
} | |||
} | |||
}, | |||
@@ -6421,14 +6442,14 @@ | |||
} | |||
}, | |||
"express": { | |||
"version": "4.16.3", | |||
"resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", | |||
"integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", | |||
"version": "4.16.4", | |||
"resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", | |||
"integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", | |||
"dev": true, | |||
"requires": { | |||
"accepts": "~1.3.5", | |||
"array-flatten": "1.1.1", | |||
"body-parser": "1.18.2", | |||
"body-parser": "1.18.3", | |||
"content-disposition": "0.5.2", | |||
"content-type": "~1.0.4", | |||
"cookie": "0.3.1", | |||
@@ -6445,10 +6466,10 @@ | |||
"on-finished": "~2.3.0", | |||
"parseurl": "~1.3.2", | |||
"path-to-regexp": "0.1.7", | |||
"proxy-addr": "~2.0.3", | |||
"qs": "6.5.1", | |||
"proxy-addr": "~2.0.4", | |||
"qs": "6.5.2", | |||
"range-parser": "~1.2.0", | |||
"safe-buffer": "5.1.1", | |||
"safe-buffer": "5.1.2", | |||
"send": "0.16.2", | |||
"serve-static": "1.13.2", | |||
"setprototypeof": "1.1.0", | |||
@@ -6464,10 +6485,10 @@ | |||
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", | |||
"dev": true | |||
}, | |||
"safe-buffer": { | |||
"version": "5.1.1", | |||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", | |||
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", | |||
"qs": { | |||
"version": "6.5.2", | |||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", | |||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", | |||
"dev": true | |||
}, | |||
"statuses": { | |||
@@ -9397,9 +9418,9 @@ | |||
"dev": true | |||
}, | |||
"ipaddr.js": { | |||
"version": "1.6.0", | |||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", | |||
"integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=", | |||
"version": "1.8.0", | |||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", | |||
"integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", | |||
"dev": true | |||
}, | |||
"is-absolute-url": { | |||
@@ -15478,6 +15499,23 @@ | |||
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", | |||
"dev": true | |||
}, | |||
"oauth2-server": { | |||
"version": "2.4.1", | |||
"resolved": "http://registry.npmjs.org/oauth2-server/-/oauth2-server-2.4.1.tgz", | |||
"integrity": "sha1-2m3QVMAh7JwpQ59dGijeY9ArcWw=", | |||
"dev": true, | |||
"requires": { | |||
"basic-auth": "~0.0.1" | |||
}, | |||
"dependencies": { | |||
"basic-auth": { | |||
"version": "0.0.1", | |||
"resolved": "http://registry.npmjs.org/basic-auth/-/basic-auth-0.0.1.tgz", | |||
"integrity": "sha1-Md22WEP2w1xv6nvrRqmHy4zhiSQ=", | |||
"dev": true | |||
} | |||
} | |||
}, | |||
"object-assign": { | |||
"version": "4.1.1", | |||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", | |||
@@ -18364,13 +18402,13 @@ | |||
} | |||
}, | |||
"proxy-addr": { | |||
"version": "2.0.3", | |||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", | |||
"integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", | |||
"version": "2.0.4", | |||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", | |||
"integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", | |||
"dev": true, | |||
"requires": { | |||
"forwarded": "~0.1.2", | |||
"ipaddr.js": "1.6.0" | |||
"ipaddr.js": "1.8.0" | |||
} | |||
}, | |||
"proxy-agent": { | |||
@@ -95,9 +95,11 @@ | |||
"babel-preset-react": "^6.23.0", | |||
"babel-preset-stage-0": "^6.22.0", | |||
"babel-runtime": "^6.23.0", | |||
"body-parser": "^1.18.3", | |||
"bundlesize": "^0.17.0", | |||
"chromedriver": "^2.38.3", | |||
"copy-webpack-plugin": "^4.0.1", | |||
"cors": "^2.8.4", | |||
"css-loader": "^0.28.11", | |||
"cypress": "^3.1.0", | |||
"dedent": "^0.7.0", | |||
@@ -108,6 +110,7 @@ | |||
"eslint-plugin-mocha": "^4.11.0", | |||
"eslint-plugin-react": "^7.10.0", | |||
"expect": "^1.20.2", | |||
"express": "^4.16.4", | |||
"extract-text-webpack-plugin": "^3.0.2", | |||
"file-loader": "^1.1.11", | |||
"git-describe": "^4.0.1", | |||
@@ -124,6 +127,7 @@ | |||
"npm-run-all": "^4.1.2", | |||
"null-loader": "0.1.1", | |||
"nyc": "^11.3.0", | |||
"oauth2-server": "^2.4.1", | |||
"open": "0.0.5", | |||
"postcss-loader": "^2.1.5", | |||
"raw-loader": "0.5.1", | |||
@@ -24,7 +24,7 @@ export default class Oauth2 extends React.Component { | |||
let username = auth && auth.get("username") || "" | |||
let clientId = auth && auth.get("clientId") || authConfigs.clientId || "" | |||
let clientSecret = auth && auth.get("clientSecret") || authConfigs.clientSecret || "" | |||
let passwordType = auth && auth.get("passwordType") || "request-body" | |||
let passwordType = auth && auth.get("passwordType") || "basic" | |||
this.state = { | |||
appName: authConfigs.appName, | |||
@@ -150,14 +150,13 @@ export default class Oauth2 extends React.Component { | |||
} | |||
</Row> | |||
<Row> | |||
<label htmlFor="password_type">type:</label> | |||
<label htmlFor="password_type">Client credentials location:</label> | |||
{ | |||
isAuthorized ? <code> { this.state.passwordType } </code> | |||
: <Col tablet={10} desktop={10}> | |||
<select id="password_type" data-name="passwordType" onChange={ this.onInputChange }> | |||
<option value="basic">Authorization header</option> | |||
<option value="request-body">Request body</option> | |||
<option value="basic">Basic auth</option> | |||
<option value="query">Query parameters</option> | |||
</select> | |||
</Col> | |||
} | |||
@@ -165,7 +164,7 @@ export default class Oauth2 extends React.Component { | |||
</Row> | |||
} | |||
{ | |||
( flow === APPLICATION || flow === IMPLICIT || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "basic") ) && | |||
( flow === APPLICATION || flow === IMPLICIT || flow === ACCESS_CODE || flow === PASSWORD ) && | |||
( !isAuthorized || isAuthorized && this.state.clientId) && <Row> | |||
<label htmlFor="client_id">client_id:</label> | |||
{ | |||
@@ -183,7 +182,7 @@ export default class Oauth2 extends React.Component { | |||
} | |||
{ | |||
( flow === APPLICATION || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "basic") ) && <Row> | |||
( (flow === APPLICATION || flow === ACCESS_CODE || flow === PASSWORD) && <Row> | |||
<label htmlFor="client_secret">client_secret:</label> | |||
{ | |||
isAuthorized ? <code> ****** </code> | |||
@@ -197,7 +196,7 @@ export default class Oauth2 extends React.Component { | |||
} | |||
</Row> | |||
} | |||
)} | |||
{ | |||
!isAuthorized && scopes && scopes.size ? <div className="scopes"> | |||
@@ -80,7 +80,7 @@ export default class LiveResponse extends React.Component { | |||
</div> | |||
} | |||
<h4>Server response</h4> | |||
<table className="responses-table"> | |||
<table className="responses-table live-responses-table"> | |||
<thead> | |||
<tr className="responses-header"> | |||
<td className="col col_header response-col_status">Code</td> | |||
@@ -74,28 +74,23 @@ export const authorizePassword = ( auth ) => ( { authActions } ) => { | |||
let { schema, name, username, password, passwordType, clientId, clientSecret } = auth | |||
let form = { | |||
grant_type: "password", | |||
scope: auth.scopes.join(scopeSeparator) | |||
scope: auth.scopes.join(scopeSeparator), | |||
username, | |||
password | |||
} | |||
let query = {} | |||
let headers = {} | |||
if ( passwordType === "basic") { | |||
headers.Authorization = "Basic " + btoa(username + ":" + password) | |||
} else { | |||
Object.assign(form, {username}, {password}) | |||
switch ( passwordType ) { | |||
case "query": | |||
setClientIdAndSecret(query, clientId, clientSecret) | |||
break | |||
switch (passwordType) { | |||
case "request-body": | |||
setClientIdAndSecret(form, clientId, clientSecret) | |||
break | |||
case "request-body": | |||
setClientIdAndSecret(form, clientId, clientSecret) | |||
break | |||
default: | |||
headers.Authorization = "Basic " + btoa(clientId + ":" + clientSecret) | |||
} | |||
case "basic": | |||
headers.Authorization = "Basic " + btoa(clientId + ":" + clientSecret) | |||
break | |||
default: | |||
console.warn(`Warning: invalid passwordType ${passwordType} was passed, not including client id and secret`) | |||
} | |||
return authActions.authorizeRequest({ body: buildFormData(form), url: schema.get("tokenUrl"), name, headers, query, auth}) | |||
@@ -0,0 +1,50 @@ | |||
// from https://github.com/pedroetb/node-oauth2-server-example | |||
var Http = require("http") | |||
var path = require("path") | |||
var express = require("express") | |||
var bodyParser = require("body-parser") | |||
var oauthserver = require("oauth2-server") | |||
var cors = require("cors") | |||
var app = express() | |||
app.use(cors()) | |||
app.use(bodyParser.urlencoded({ extended: true })) | |||
app.use(bodyParser.json()) | |||
app.oauth = oauthserver({ | |||
model: require("./model.js"), | |||
grants: ["password", "client_credentials", "implicit"], | |||
debug: true | |||
}) | |||
app.all("/oauth/token", app.oauth.grant()) | |||
app.get("/swagger.yaml", function (req, res) { | |||
res.sendFile(path.join(__dirname, "swagger.yaml")) | |||
}) | |||
app.get("*", app.oauth.authorise(), function (req, res) { | |||
res.send("Secret secrets are no fun, secret secrets hurt someone.") | |||
}) | |||
app.use(app.oauth.errorHandler()) | |||
function startServer() { | |||
var httpServer = Http.createServer(app) | |||
httpServer.listen("3231") | |||
return function stopServer() { | |||
httpServer.close() | |||
} | |||
} | |||
module.exports = startServer | |||
if (require.main === module) { | |||
// for debugging | |||
startServer() | |||
} |
@@ -0,0 +1,141 @@ | |||
// from https://github.com/pedroetb/node-oauth2-server-example | |||
var config = { | |||
clients: [{ | |||
clientId: "application", | |||
clientSecret: "secret" | |||
}], | |||
confidentialClients: [{ | |||
clientId: "confidentialApplication", | |||
clientSecret: "topSecret" | |||
}], | |||
tokens: [], | |||
users: [{ | |||
id: "123", | |||
username: "swagger", | |||
password: "password" | |||
}] | |||
} | |||
/** | |||
* Dump the memory storage content (for debug). | |||
*/ | |||
var dump = function () { | |||
console.log("clients", config.clients) | |||
console.log("confidentialClients", config.confidentialClients) | |||
console.log("tokens", config.tokens) | |||
console.log("users", config.users) | |||
} | |||
/* | |||
* Methods used by all grant types. | |||
*/ | |||
var getAccessToken = function (bearerToken, callback) { | |||
var tokens = config.tokens.filter(function (token) { | |||
return token.accessToken === bearerToken | |||
}) | |||
return callback(false, tokens[0]) | |||
} | |||
var getClient = function (clientId, clientSecret, callback) { | |||
var clients = config.clients.filter(function (client) { | |||
return client.clientId === clientId && client.clientSecret === clientSecret | |||
}) | |||
var confidentialClients = config.confidentialClients.filter(function (client) { | |||
return client.clientId === clientId && client.clientSecret === clientSecret | |||
}) | |||
callback(false, clients[0] || confidentialClients[0]) | |||
} | |||
var grantTypeAllowed = function (clientId, grantType, callback) { | |||
var clientsSource, | |||
clients = [] | |||
if (grantType === "password") { | |||
clientsSource = config.clients | |||
} else if (grantType === "client_credentials") { | |||
clientsSource = config.confidentialClients | |||
} | |||
if (clientsSource) { | |||
clients = clientsSource.filter(function (client) { | |||
return client.clientId === clientId | |||
}) | |||
} | |||
callback(false, clients.length) | |||
} | |||
var saveAccessToken = function (accessToken, clientId, expires, user, callback) { | |||
config.tokens.push({ | |||
accessToken: accessToken, | |||
expires: expires, | |||
clientId: clientId, | |||
user: user | |||
}) | |||
callback(false) | |||
} | |||
/* | |||
* Method used only by password grant type. | |||
*/ | |||
var getUser = function (username, password, callback) { | |||
var users = config.users.filter(function (user) { | |||
return user.username === username && user.password === password | |||
}) | |||
callback(false, users[0]) | |||
} | |||
/* | |||
* Method used only by client_credentials grant type. | |||
*/ | |||
var getUserFromClient = function (clientId, clientSecret, callback) { | |||
var clients = config.confidentialClients.filter(function (client) { | |||
return client.clientId === clientId && client.clientSecret === clientSecret | |||
}) | |||
var user | |||
if (clients.length) { | |||
user = { | |||
username: clientId | |||
} | |||
} | |||
callback(false, user) | |||
} | |||
/** | |||
* Export model definition object. | |||
*/ | |||
module.exports = { | |||
getAccessToken: getAccessToken, | |||
getClient: getClient, | |||
grantTypeAllowed: grantTypeAllowed, | |||
saveAccessToken: saveAccessToken, | |||
getUser: getUser, | |||
getUserFromClient: getUserFromClient | |||
} |
@@ -0,0 +1,36 @@ | |||
swagger: "2.0" | |||
host: localhost:3231 | |||
paths: | |||
/password: | |||
get: | |||
summary: OAuth2 Password | |||
security: | |||
- oauthPassword: [] | |||
responses: | |||
200: | |||
description: OK | |||
schema: | |||
type: string | |||
/application: | |||
get: | |||
summary: OAuth2 Application | |||
security: | |||
- oauthApplication: [] | |||
responses: | |||
200: | |||
description: OK | |||
schema: | |||
type: string | |||
securityDefinitions: | |||
oauthPassword: | |||
type: oauth2 | |||
flow: password | |||
tokenUrl: /oauth/token | |||
oauthApplication: | |||
type: oauth2 | |||
flow: application | |||
tokenUrl: /oauth/token | |||
oauthImplicit: | |||
type: oauth2 | |||
flow: implicit | |||
authorizationUrl: /oauth/token |
@@ -1,3 +1,4 @@ | |||
const startOAuthServer = require("../helpers/oauth2-server") | |||
// *********************************************************** | |||
// This example plugins/index.js can be used to load plugins | |||
// | |||
@@ -12,6 +13,7 @@ | |||
// the project's config changing) | |||
module.exports = (on, config) => { | |||
startOAuthServer() | |||
// `on` is used to hook into various events Cypress emits | |||
// `config` is the resolved Cypress config | |||
} |
@@ -18,3 +18,10 @@ import "./commands" | |||
// Alternatively you can use CommonJS syntax: | |||
// require('./commands') | |||
// Remove fetch, so Cypress can intercept XHRs | |||
// see https://github.com/cypress-io/cypress/issues/95 | |||
Cypress.on("window:before:load", win => { | |||
win.fetch = null | |||
}) |
@@ -0,0 +1,55 @@ | |||
describe("OAuth2 Application flow", function() { | |||
beforeEach(() => { | |||
cy.server() | |||
cy.route({ | |||
url: "**/oauth/*", | |||
method: "POST" | |||
}).as("tokenRequest") | |||
}) | |||
it("should make an application flow Authorization header request", () => { | |||
cy | |||
.visit("/?url=http://localhost:3231/swagger.yaml") | |||
.get(".btn.authorize") | |||
.click() | |||
.get("div.modal-ux-content > div:nth-child(2)").within(() => { | |||
cy.get("#client_id") | |||
.clear() | |||
.type("confidentialApplication") | |||
.get("#client_secret") | |||
.clear() | |||
.type("topSecret") | |||
.get("button.btn.modal-btn.auth.authorize.button") | |||
.click() | |||
}) | |||
cy.get("button.close-modal") | |||
.click() | |||
.get("#operations-default-get_application") | |||
.click() | |||
.get(".btn.try-out__btn") | |||
.click() | |||
.get(".btn.execute") | |||
.click() | |||
cy.get("@tokenRequest") | |||
.its("request") | |||
.its("body") | |||
.should("equal", "grant_type=client_credentials") | |||
cy.get("@tokenRequest") | |||
.its("request") | |||
.its("headers") | |||
.its("authorization") | |||
.should("equal", "Basic Y29uZmlkZW50aWFsQXBwbGljYXRpb246dG9wU2VjcmV0") | |||
.get(".live-responses-table .response-col_status") | |||
.contains("200") | |||
}) | |||
}) |
@@ -0,0 +1,122 @@ | |||
describe("OAuth2 Password flow", function() { | |||
beforeEach(() => { | |||
cy.server() | |||
cy.route({ | |||
url: "**/oauth/*", | |||
method: "POST" | |||
}).as("tokenRequest") | |||
}) | |||
it("should make a password flow Authorization header request", () => { | |||
cy | |||
.visit("/?url=http://localhost:3231/swagger.yaml") | |||
.get(".btn.authorize") | |||
.click() | |||
.get("#oauth_username") | |||
.type("swagger") | |||
.get("#oauth_password") | |||
.type("password") | |||
.get("#password_type") | |||
.select("basic") | |||
.get("#client_id") | |||
.clear() | |||
.type("application") | |||
.get("#client_secret") | |||
.clear() | |||
.type("secret") | |||
.get("div.modal-ux-content > div:nth-child(1) > div > div:nth-child(2) > div > div.auth-btn-wrapper > button.btn.modal-btn.auth.authorize.button") | |||
.click() | |||
.get("button.close-modal") | |||
.click() | |||
.get("#operations-default-get_password") | |||
.click() | |||
.get(".btn.try-out__btn") | |||
.click() | |||
.get(".btn.execute") | |||
.click() | |||
cy.get("@tokenRequest") | |||
.its("request") | |||
.its("body") | |||
.should("include", "grant_type=password") | |||
.should("include", "username=swagger") | |||
.should("include", "password=password") | |||
.should("not.include", "client_id") | |||
.should("not.include", "client_secret") | |||
cy.get("@tokenRequest") | |||
.its("request") | |||
.its("headers") | |||
.its("authorization") | |||
.should("equal", "Basic YXBwbGljYXRpb246c2VjcmV0") | |||
.get(".live-responses-table .response-col_status") | |||
.contains("200") | |||
}) | |||
it("should make a Password flow request-body request", () => { | |||
cy | |||
.visit("/?url=http://localhost:3231/swagger.yaml") | |||
.get(".btn.authorize") | |||
.click() | |||
.get("#oauth_username") | |||
.type("swagger") | |||
.get("#oauth_password") | |||
.type("password") | |||
.get("#password_type") | |||
.select("request-body") | |||
.get("#client_id") | |||
.clear() | |||
.type("application") | |||
.get("#client_secret") | |||
.clear() | |||
.type("secret") | |||
.get("div.modal-ux-content > div:nth-child(1) > div > div:nth-child(2) > div > div.auth-btn-wrapper > button.btn.modal-btn.auth.authorize.button") | |||
.click() | |||
.get("button.close-modal") | |||
.click() | |||
.get("#operations-default-get_password") | |||
.click() | |||
.get(".btn.try-out__btn") | |||
.click() | |||
.get(".btn.execute") | |||
.click() | |||
cy.get("@tokenRequest") | |||
.its("request") | |||
.its("body") | |||
.should("include", "grant_type=password") | |||
.should("include", "username=swagger") | |||
.should("include", "password=password") | |||
.should("include", "client_id=application") | |||
.should("include", "client_secret=secret") | |||
cy.get("@tokenRequest") | |||
.its("request") | |||
.its("headers") | |||
.should("not.have.property", "authorization") | |||
.get(".live-responses-table .response-col_status") | |||
.contains("200") | |||
}) | |||
}) |