Add a cypress test for SSO login (#11401)

* Allow `startHomeserver` to take an options object

... so that we can add more options

* Add a Cypress test for SSO login
This commit is contained in:
Richard van der Hoff 2023-08-14 12:08:12 +01:00 committed by GitHub
parent 6f455217d1
commit f65c6726c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 574 additions and 19 deletions

View file

@ -0,0 +1,24 @@
# oauth_server
A very simple OAuth identity provider server.
The following endpoints are exposed:
- `/oauth/auth.html`: An OAuth2 [authorization endpoint](https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint).
In a proper OAuth2 system, this would prompt the user to log in; we just give a big "Submit" button (and an
auth code that can be changed if we want the next step to fail). It redirects back to the calling application
with a "code".
- `/oauth/token`: An OAuth2 [token endpoint](https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint).
Receives the code issued by "auth.html" and, if it is valid, exchanges it for an OAuth2 access token.
- `/oauth/userinfo`: An OAuth2 [userinfo endpoint](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo).
Returns details about the owner of the offered access token.
To start the server, do:
```javascript
cy.task("startOAuthServer").then((port) => {
// now we can configure Synapse or Element to talk to the OAuth2 server.
});
```

View file

@ -0,0 +1,81 @@
/*
Copyright 2023 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import http from "http";
import express from "express";
import { AddressInfo } from "net";
import PluginEvents = Cypress.PluginEvents;
import PluginConfigOptions = Cypress.PluginConfigOptions;
const servers: http.Server[] = [];
function startOAuthServer(html: string): number {
const app = express();
// static files. This includes the "authorization endpoint".
app.use(express.static(__dirname + "/res"));
// token endpoint (see https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint)
app.use("/oauth/token", express.urlencoded());
app.post("/oauth/token", (req, res) => {
// if the code is valid, accept it. Otherwise, return an error.
const code = req.body.code;
if (code === "valid_auth_code") {
res.send({
access_token: "oauth_access_token",
token_type: "Bearer",
expires_in: "3600",
});
} else {
res.send({ error: "bad auth code" });
}
});
// userinfo endpoint (see https://openid.net/specs/openid-connect-core-1_0.html#UserInfo)
app.get("/oauth/userinfo", (req, res) => {
// TODO: validate that the request carries an auth header which matches the access token we issued above
// return an OAuth2 user info object
res.send({
sub: "alice",
name: "Alice",
});
});
const server = http.createServer(app);
server.listen();
servers.push(server);
const address = server.address() as AddressInfo;
console.log(`Started OAuth server at ${address.address}:${address.port}`);
return address.port;
}
function stopOAuthServer(): null {
console.log("Stopping OAuth servers");
for (const server of servers) {
const address = server.address() as AddressInfo;
server.close();
console.log(`Stopped OAuth server at ${address.address}:${address.port}`);
}
servers.splice(0, servers.length); // clear
return null;
}
export function oAuthServer(on: PluginEvents, config: PluginConfigOptions) {
on("task", { startOAuthServer, stopOAuthServer });
on("after:run", stopOAuthServer);
}

View file

@ -0,0 +1,42 @@
<!--
Copyright 2023 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
A dummy OAuth2 authorization endpoint (see https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint)
Mostly, it just redirects back to the `redirect_uri` in the query params.
-->
<html lang="en">
<body>
<h1>Test OAuth page</h1>
<form id="auth_form">
<input type="hidden" id="state" name="state" />
<label for="code">Auth Code:</label>
<input type="text" id="code" name="code" value="valid_auth_code" />
<input type="submit" value="Submit" />
</form>
<script>
// process the query params, and set up the form
const urlParams = new URLSearchParams(window.location.search);
console.log("Test OAuth page: query params:", new Map(urlParams.entries()));
document.getElementById("auth_form").action = urlParams.get("redirect_uri");
document.getElementById("state").value = urlParams.get("state");
</script>
</body>
</html>