diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml index cc3da93..41f1055 100644 --- a/.idea/jsLibraryMappings.xml +++ b/.idea/jsLibraryMappings.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json index f25c481..ed70959 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -427,6 +427,11 @@ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", "dev": true }, + "@types/url-join": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/url-join/-/url-join-4.0.0.tgz", + "integrity": "sha512-awrJu8yML4E/xTwr2EMatC+HBnHGoDxc2+ImA9QyeUELI1S7dOCIZcyjki1rkwoA8P2D2NVgLAJLjnclkdLtAw==" + }, "@types/ws": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.0.tgz", @@ -2076,11 +2081,41 @@ "resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.0.tgz", "integrity": "sha512-Jm2LMTB5rsJqlS1+cmgqqM9tTs0UrlgYR7TvDT3ZgXsUI5ib1NjQlqZHf+tDK5tVPdFGwyq02wAoJtyYIRSiFA==" }, + "fastify-http-proxy": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fastify-http-proxy/-/fastify-http-proxy-4.2.0.tgz", + "integrity": "sha512-qxIj5AHrt4sgTVggv1km+dr1105gzHRk39/rhzuNIUy747m2WswsLM+ZeedulK/EGYSTNluKwNhbqwPSZ4JvnA==", + "requires": { + "fastify-reply-from": "^3.1.3", + "ws": "^7.4.1" + }, + "dependencies": { + "ws": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.2.tgz", + "integrity": "sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA==" + } + } + }, "fastify-plugin": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.0.tgz", "integrity": "sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w==" }, + "fastify-reply-from": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fastify-reply-from/-/fastify-reply-from-3.5.0.tgz", + "integrity": "sha512-kNc0taosEyZz1DZBo/Dt4ihxF210gqalhRAiKFKT0VvGCL/+3A1JunlY/ExeoJUyfiCUWpRJ87pj4FCdrhbZLA==", + "requires": { + "end-of-stream": "^1.4.1", + "fastify-plugin": "^3.0.0", + "http-errors": "^1.8.0", + "pump": "^3.0.0", + "semver": "^7.2.1", + "tiny-lru": "^7.0.0", + "undici": "^2.1.0" + } + }, "fastify-sensible": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/fastify-sensible/-/fastify-sensible-3.1.0.tgz", @@ -4118,6 +4153,11 @@ "random-bytes": "~1.0.0" } }, + "undici": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-2.2.1.tgz", + "integrity": "sha512-21sJmMvJOMsyt/2pQPgB5Ruvm2ADTTm34NHRy4kzfeW9uMO7gK2oN0f+5KaJCmoKGJb8KxdU6yWpW0SphFHadw==" + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -4131,6 +4171,11 @@ "punycode": "^2.1.0" } }, + "url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/backend/package.json b/backend/package.json index b0cfc3f..c92dc4e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -17,11 +17,13 @@ "@types/express": "^4.17.10", "@types/lodash": "^4.14.167", "@types/node": "^14.14.21", + "@types/url-join": "^4.0.0", "@wulkanowy/sdk": "^0.1.1", "apollo-server-fastify": "^2.19.2", "dotenv": "^8.2.0", "fastify": "^3.10.1", "fastify-cookie": "^5.1.0", + "fastify-http-proxy": "^4.2.0", "fastify-sensible": "^3.1.0", "fastify-session": "^5.2.1", "lodash": "^4.17.20", @@ -32,7 +34,8 @@ "ts-node": "^9.1.1", "type-graphql": "^1.1.1", "typeorm": "^0.2.30", - "typescript": "^4.1.3" + "typescript": "^4.1.3", + "url-join": "^4.0.1" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^4.13.0", diff --git a/backend/src/constants.ts b/backend/src/constants.ts index 53f3521..96e9079 100644 --- a/backend/src/constants.ts +++ b/backend/src/constants.ts @@ -4,3 +4,5 @@ export const scopes = [ 'notes', 'achievements', ]; + +export const websitePrefix = '/'; diff --git a/backend/src/index.ts b/backend/src/index.ts index 4828588..dec51d2 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -5,8 +5,10 @@ dotenv.config(); import Fastify from 'fastify'; import FastifyCookie from 'fastify-cookie'; +import FastifyHttpProxy from 'fastify-http-proxy'; import FastifySensible from 'fastify-sensible'; import FastifySession from 'fastify-session'; +import { websitePrefix } from './constants'; import database from './database/database'; import registerOAuth from './routes/oauth2'; import registerWebsiteApi from './routes/website-api'; @@ -28,6 +30,15 @@ async function start() { secure: false, // TODO: Remove this line or add development env variable }, }); + + const websiteProxyUpstream = process.env.PROXY_WEBSITE; + if (websiteProxyUpstream !== undefined) { + await server.register(FastifyHttpProxy, { + upstream: websiteProxyUpstream, + prefix: websitePrefix, + }); + } + await server.register(registerOAuth, { prefix: '/api/oauth', logLevel: 'info' }); await server.register(registerWebsiteApi, { prefix: '/api/website', logLevel: 'info' }); diff --git a/backend/src/routes/oauth2/authorize.ts b/backend/src/routes/oauth2/authorize.ts index d043bdd..e05ed80 100644 --- a/backend/src/routes/oauth2/authorize.ts +++ b/backend/src/routes/oauth2/authorize.ts @@ -1,6 +1,7 @@ import _ from 'lodash'; import { nanoid } from 'nanoid'; -import { scopes } from '../../constants'; +import urlJoin from 'url-join'; +import { scopes, websitePrefix } from '../../constants'; import database from '../../database/database'; import { ParamError, ScopeError } from '../../errors'; import type { MyFastifyInstance, StudentsMode } from '../../types'; @@ -10,7 +11,7 @@ import { } from '../../utils'; export default function registerAuthorize(server: MyFastifyInstance): void { - server.post('/authorize', async ( + server.get('/authorize', async ( request, reply, ) => { @@ -80,7 +81,7 @@ export default function registerAuthorize(server: MyFastifyInstance): void { studentsMode, }); - await reply.redirect(`/authenticate-prompt?prompt_id=${promptId}`); + await reply.redirect(urlJoin(websitePrefix, `/authenticate-prompt?prompt_id=${promptId}`)); return; } await reply.redirect(`${request.query.redirect_uri}?error=unsupported_response_type`); diff --git a/backend/src/routes/website-api/index.ts b/backend/src/routes/website-api/index.ts index f890b30..5bd7a95 100644 --- a/backend/src/routes/website-api/index.ts +++ b/backend/src/routes/website-api/index.ts @@ -1,7 +1,8 @@ import { ApolloServer } from 'apollo-server-fastify'; import { buildSchema } from 'type-graphql'; +import { ParamError } from '../../errors'; import type { ApolloContext, MyFastifyInstance } from '../../types'; -import { getSessionData } from '../../utils'; +import { getSessionData, isObject, validateParam } from '../../utils'; import LoginResolver from './resolvers/login-resolver'; import PromptInfoResolver from './resolvers/prompt-info-resolver'; import type { WebsiteAPIContext } from './types'; @@ -26,5 +27,26 @@ export default async function registerWebsiteApi(server: MyFastifyInstance): Pro origin: false, }, })); - console.log(apolloServer.graphqlPath); + + server.get('/deny', async ( + request, + reply, + ) => { + if (!isObject(request.query)) { + server.log.warn('Request query is not an object'); + throw server.httpErrors.badRequest(); + } + try { + validateParam('prompt_id', request.query.prompt_id); + } catch (error) { + if (error instanceof ParamError) { + throw server.httpErrors.badRequest(error.message); + } + server.log.error(error); + throw server.httpErrors.internalServerError(); + } + const prompt = getSessionData(request.session).prompts.get(request.query.prompt_id); + if (!prompt) throw server.httpErrors.badRequest('Prompt data not found'); + await reply.redirect(`${prompt.redirectUri}?error=access_denied&error_description=${encodeURIComponent('User denied')}`); + }); } diff --git a/website/src/pages/authenticate-prompt/app.vue b/website/src/pages/authenticate-prompt/app.vue index aa82a2f..cf79c4b 100644 --- a/website/src/pages/authenticate-prompt/app.vue +++ b/website/src/pages/authenticate-prompt/app.vue @@ -7,7 +7,10 @@ - + + Brak wymaganego parametru prompt_id + + Nie udało się wczytać danych