From 6b4ad819407bda42ca4e160299548f9944c681c1 Mon Sep 17 00:00:00 2001 From: Fabian Stamm Date: Wed, 28 Oct 2020 05:11:47 +0100 Subject: [PATCH] Adding a popup authentication option. --- .drone.yml | 3 +- Dockerfile | 14 ++----- locales/de.json | 83 +++++++++++++++++++------------------- src/api/user/index.ts | 12 ++++-- src/api/user/jwt.ts | 37 +++++++++++++++++ src/testdata.ts | 2 +- src/views/popup.ts | 21 ++++++++++ src/views/views.ts | 63 ++++++++++++++++------------- views/src/popup/popup.hbs | 24 +++++++++++ views/src/popup/popup.js | 32 +++++++++++++++ views/src/popup/popup.scss | 63 +++++++++++++++++++++++++++++ 11 files changed, 267 insertions(+), 87 deletions(-) create mode 100644 src/api/user/jwt.ts create mode 100644 src/views/popup.ts create mode 100644 views/src/popup/popup.hbs create mode 100644 views/src/popup/popup.js create mode 100644 views/src/popup/popup.scss diff --git a/.drone.yml b/.drone.yml index 4cbd902..49b0368 100644 --- a/.drone.yml +++ b/.drone.yml @@ -6,6 +6,7 @@ steps: - name: Build with node image: node:12 commands: + - npm config set registry https://npm.hibas123.de - npm install - npm run install - npm run build @@ -21,7 +22,7 @@ steps: registry: hibas123.azurecr.io debug: true when: - branch: master + branch: [master] event: exclude: - pull_request diff --git a/Dockerfile b/Dockerfile index a3d444e..44b98de 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,20 +2,12 @@ FROM node:12 LABEL maintainer="Fabian Stamm " -# RUN apt-get update - -# # for https -# RUN apt-get install -yyq ca-certificates -# # install libraries -# RUN apt-get install -yyq libappindicator1 libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 -# # tools -# RUN apt-get install -yyq gconf-service lsb-release wget xdg-utils -# # and fonts -# RUN apt-get install -yyq fonts-liberation RUN mkdir -p /usr/src/app WORKDIR /usr/src/app +RUN npm config set registry https://npm.hibas123.de + COPY ["package.json", "package-lock.json", "tsconfig.json", "/usr/src/app/"] ENV NODE_ENV=production @@ -30,4 +22,4 @@ VOLUME [ "/usr/src/app/logs", "/usr/src/app/keys"] EXPOSE 3004/tcp -CMD ["npm", "run", "start"] \ No newline at end of file +CMD ["npm", "run", "start"] diff --git a/locales/de.json b/locales/de.json index 19ab808..9d37add 100644 --- a/locales/de.json +++ b/locales/de.json @@ -1,42 +1,43 @@ { - "User not found": "Benutzer nicht gefunden", - "Password or username wrong": "Passwort oder Benutzername falsch", - "Authorize %s": "Authorize %s", - "Login": "Einloggen", - "You are not logged in or your login is expired": "Du bist nicht länger angemeldet oder deine Anmeldung ist abgelaufen.", - "Username or Email": "Benutzername oder Email", - "Password": "Passwort", - "Next": "Weiter", - "Register": "Registrieren", - "Mail": "Mail", - "Repeat Password": "Passwort wiederholen", - "Username": "Benutzername", - "Name": "Name", - "Registration code": "Registrierungs Schlüssel", - "You need to select one of the options": "Du musst eine der Optionen auswälen", - "Male": "Mann", - "Female": "Frau", - "Other": "Anderes", - "Registration code required": "Registrierungs Schlüssel benötigt", - "Username required": "Benutzername benötigt", - "Name required": "Name benötigt", - "Mail required": "Mail benötigt", - "The passwords do not match": "Die Passwörter stimmen nicht überein", - "Password is required": "Password benötigt", - "Invalid registration code": "Ungültiger Registrierungs Schlüssel", - "Username taken": "Benutzername nicht verfügbar", - "Mail linked with other account": "Mail ist bereits mit einem anderen Account verbunden", - "Registration code already used": "Registrierungs Schlüssel wurde bereits verwendet", - "Administration": "Administration", - "Field {{field}} is not defined": "Feld {{field}} fehlt", - "Field {{field}} has wrong type. It should be from type {{type}}": "Feld {{field}} hat den falschen Typ. Es sollte vom Typ {{type}} sein", - "Client has no permission for acces password auth": "Dieser Client hat keine Berechtigung password auth zu benutzen", - "Invalid token": "Ungültiger Token", - "By clicking on ALLOW, you allow this app to access the requested recources.": "Wenn sie ALLOW drücken, berechtigen sie die Applikation die beantragten Resourcen zu benutzen.", - "User": "User", - "No special token": "No special token", - "Login token invalid": "Login token invalid", - "No login token": "No login token", - "You are not logged in or your login is expired (Login token invalid)": "You are not logged in or your login is expired (Login token invalid)", - "You are not logged in or your login is expired (No special token)": "You are not logged in or your login is expired (No special token)" -} + "User not found": "Benutzer nicht gefunden", + "Password or username wrong": "Passwort oder Benutzername falsch", + "Authorize %s": "Authorize %s", + "Login": "Einloggen", + "You are not logged in or your login is expired": "Du bist nicht länger angemeldet oder deine Anmeldung ist abgelaufen.", + "Username or Email": "Benutzername oder Email", + "Password": "Passwort", + "Next": "Weiter", + "Register": "Registrieren", + "Mail": "Mail", + "Repeat Password": "Passwort wiederholen", + "Username": "Benutzername", + "Name": "Name", + "Registration code": "Registrierungs Schlüssel", + "You need to select one of the options": "Du musst eine der Optionen auswälen", + "Male": "Mann", + "Female": "Frau", + "Other": "Anderes", + "Registration code required": "Registrierungs Schlüssel benötigt", + "Username required": "Benutzername benötigt", + "Name required": "Name benötigt", + "Mail required": "Mail benötigt", + "The passwords do not match": "Die Passwörter stimmen nicht überein", + "Password is required": "Password benötigt", + "Invalid registration code": "Ungültiger Registrierungs Schlüssel", + "Username taken": "Benutzername nicht verfügbar", + "Mail linked with other account": "Mail ist bereits mit einem anderen Account verbunden", + "Registration code already used": "Registrierungs Schlüssel wurde bereits verwendet", + "Administration": "Administration", + "Field {{field}} is not defined": "Feld {{field}} fehlt", + "Field {{field}} has wrong type. It should be from type {{type}}": "Feld {{field}} hat den falschen Typ. Es sollte vom Typ {{type}} sein", + "Client has no permission for acces password auth": "Dieser Client hat keine Berechtigung password auth zu benutzen", + "Invalid token": "Ungültiger Token", + "By clicking on ALLOW, you allow this app to access the requested recources.": "Wenn sie ALLOW drücken, berechtigen sie die Applikation die beantragten Resourcen zu benutzen.", + "User": "User", + "No special token": "No special token", + "Login token invalid": "Login token invalid", + "No login token": "No login token", + "You are not logged in or your login is expired (Login token invalid)": "You are not logged in or your login is expired (Login token invalid)", + "You are not logged in or your login is expired (No special token)": "You are not logged in or your login is expired (No special token)", + "Special token invalid": "Special token invalid" +} \ No newline at end of file diff --git a/src/api/user/index.ts b/src/api/user/index.ts index 2df9f0c..4d54321 100644 --- a/src/api/user/index.ts +++ b/src/api/user/index.ts @@ -1,10 +1,11 @@ import { Router } from "express"; -import Register from "./register"; -import Login from "./login"; -import TwoFactorRoute from "./twofactor"; -import { GetToken, DeleteToken } from "./token"; import { GetAccount } from "./account"; import { GetContactInfos } from "./contact"; +import { GetJWTByUser } from "./jwt"; +import Login from "./login"; +import Register from "./register"; +import { DeleteToken, GetToken } from "./token"; +import TwoFactorRoute from "./twofactor"; const UserRoute: Router = Router(); @@ -125,4 +126,7 @@ UserRoute.get("/account", GetAccount); * @apiSuccess {Object[]} user.phone Phone numbers */ UserRoute.get("/contact", GetContactInfos); + +UserRoute.get("/jwt", GetJWTByUser); + export default UserRoute; diff --git a/src/api/user/jwt.ts b/src/api/user/jwt.ts new file mode 100644 index 0000000..eb3bb82 --- /dev/null +++ b/src/api/user/jwt.ts @@ -0,0 +1,37 @@ +import { Request, Response } from "express"; +import Stacker from "../middlewares/stacker"; +import { GetUserMiddleware } from "../middlewares/user"; +import { URL } from "url"; +import Client from "../../models/client"; +import RequestError, { HttpStatusCode } from "../../helper/request_error"; +import { getAccessTokenJWT } from "../../helper/jwt"; + +export const GetJWTByUser = Stacker( + GetUserMiddleware(true, false), + async (req: Request, res: Response) => { + const { client_id, origin } = req.query as { [key: string]: string }; + + const client = await Client.findOne({ + client_id, + }); + + const clientNotFoundError = new RequestError( + "Client not found!", + HttpStatusCode.BAD_REQUEST + ); + + if (!client) throw clientNotFoundError; + + const clientUrl = new URL(client.redirect_url); + + if (clientUrl.hostname !== origin) throw clientNotFoundError; + + const jwt = await getAccessTokenJWT({ + user: req.user, + client: client, + permissions: [], + }); + + res.json({ jwt }); + } +); diff --git a/src/testdata.ts b/src/testdata.ts index c001f19..b540e60 100644 --- a/src/testdata.ts +++ b/src/testdata.ts @@ -62,7 +62,7 @@ export default async function TestData() { await Client.save(c); } - let perm = await Permission.findOne({ id: 0 }); + let perm = await Permission.findById("507f1f77bcf86cd799439011"); if (!perm) { Logging.log("Adding test permission"); perm = Permission.new({ diff --git a/src/views/popup.ts b/src/views/popup.ts new file mode 100644 index 0000000..5ee5814 --- /dev/null +++ b/src/views/popup.ts @@ -0,0 +1,21 @@ +import * as handlebars from "handlebars"; +import { readFileSync } from "fs"; +import { __ as i__ } from "i18n"; +import config from "../config"; + +let template: handlebars.TemplateDelegate; +function loadStatic() { + let html = readFileSync("./views/out/popup/popup.html").toString(); + template = handlebars.compile(html); +} + +export default function GetPopupPage(__: typeof i__): string { + if (config.core.dev) { + loadStatic(); + } + + let data = {}; + return template(data, { helpers: { i18n: __ } }); +} + +loadStatic(); diff --git a/src/views/views.ts b/src/views/views.ts index 1f16e96..f8acc67 100644 --- a/src/views/views.ts +++ b/src/views/views.ts @@ -1,9 +1,9 @@ import { IRouter, Request, + RequestHandler, Router, static as ServeStatic, - RequestHandler, } from "express"; import * as Handlebars from "handlebars"; import * as moment from "moment"; @@ -13,6 +13,7 @@ import config from "../config"; import { HttpStatusCode } from "../helper/request_error"; import GetAdminPage from "./admin"; import GetAuthPage from "./authorize"; +import GetPopupPage from "./popup"; import GetRegistrationPage from "./register"; Handlebars.registerHelper("appname", () => config.core.name); @@ -68,33 +69,37 @@ ViewRouter.get( ViewRouter.get("/auth", GetAuthRoute(true)); -if (config.core.dev) { - const logo = - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAASdAAAEnQB3mYfeAAAAAZiS0dEAP8A/wD/oL2nkwAAAFR0RVh0Y29tbWVudABGaWxlIHNvdXJjZTogaHR0cHM6Ly9jb21tb25zLndpa2ltZWRpYS5vcmcvd2lraS9GaWxlOkdvb2dsZS1mYXZpY29uLTIwMTUucG5nLE0iZQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNS0wOS0wMlQxNzo1ODowOCswMDowMNkAVU4AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDktMDJUMTc6NTg6MDgrMDA6MDCoXe3yAAAAR3RFWHRzb2Z0d2FyZQBJbWFnZU1hZ2ljayA2LjcuNy0xMCAyMDE0LTAzLTA2IFExNiBodHRwOi8vd3d3LmltYWdlbWFnaWNrLm9yZ2+foqIAAAAYdEVYdFRodW1iOjpEb2N1bWVudDo6UGFnZXMAMaf/uy8AAAAYdEVYdFRodW1iOjpJbWFnZTo6aGVpZ2h0ADQwMUEAWp0AAAAXdEVYdFRodW1iOjpJbWFnZTo6V2lkdGgAMzk0OUtQUwAAABl0RVh0VGh1bWI6Ok1pbWV0eXBlAGltYWdlL3BuZz+yVk4AAAAXdEVYdFRodW1iOjpNVGltZQAxNDQxMjE2Njg4mYj7RAAAABN0RVh0VGh1bWI6OlNpemUAMTcuN0tCQhK/wrgAAAAzdEVYdFRodW1iOjpVUkkAZmlsZTovLy90bXAvbG9jYWxjb3B5XzFmZGViZjk0YmZkZC0xLnBuZ8EhOmkAAAkUSURBVGhDzZkLcBXVGcf/u/f9yM07gDq06Rh5BZTAtKMVwQGqaFEZmNLWgoBO1RRFausjbR1qKR0rHUDFtwVtqWPHgc4UmBq1NASUiFQGwiskMqZMSW6Tm+Q+knvvvvp9u0uamNxXctO5P9i5u+ec3T3/c77zfd/ZCBqBMUANhaB2+Ok3CMgSYLVC9ORBLC2F6CswW2WPrAmJHa5D9EAtpGMNkC+2AvE4IIrGcRlV1Q/BRqLGXwn7zNlwzF0A54JbqVIw2oyQUQmRms4g8voLiB14H5qiQHS5AJsNsFghCIk7pr+S2kOSoMWi+r2OG+fBc99a2K+tMltlxoiESKdPIvirGvo9ATHPB9gdEAaOfIboXYjHoAaDsF59DXy/+A3s180ya9MjIyGaLKP70QdoBmohFhSRidDoJxn5jKGuaLSe1K4uMrn5KNj6GgSLxaxMTtpCYh/VoXv9/fRgK0AmlMx0Rg0LivbpA1e4fQfss683KxKTlj2EXtiMrgdWQHB76HCPrQiGni+46D30vsDq7yD00hazIjEphfTUPILIGy+S2xyX9jRnDV53Ah0SecAUJDWtnifXIVq7j9ZD4cjWApuIecroT0jzOdwt9T9+eH/8M3hX/dAsTUxCIcFtz6D3zVdgKSzOSITGsYJiiEZeCGTjPKoamwq/hutoVgXycrDbE86wIaIdeY9vgOfuNWZpcoYVEj10AN3V9xjmlO4IUqe1cAiC0wX79XNg/+Zc2KZUQiwuheBwQCPz0Do7IDWfI8dxEPFD/4AW7IFA7lugqH8ZXYSfRPx8IzzLV5qlqRkihIOT/+uTIOQXpBUb+HbukFhUDO9Dj8H17SVmTWqif38Pod9thNrepr+PUf1t8G34LdxLv6dfp8sQIYEHV0I+8U/da6SCRauBThLwE3gpKo+UMGUH4eeeJRUKfL/eCvedy8ya9BkkJHa0EV2rbqc8qCylSWlmelH89l9hLb/aLB05sSOHoHxxAe7lK8ySzBgkJL7/K+jZ5oMa9kJ0Ui6UQIu+HkhE6YdHIZKvzwX6F4EapE6JrSj6ZSMc0wNQQjb2nkNgr6R2B1C6rz5nRDD9QrTmGmh0pUWs8N3bBN/3m2kRkxiFpsUUxJOnBjpQsJkCJC3uXKLftKT95Ovt5Nc5klLPBZcCpdNJplYJNSqSC+X4EIO1YhKKfv9nviWn0GdE7dhrrAddBCNA66PNjy+Ooqc/hb0iSDHCSibVjfxNW802uYXec82/e4CRDUCmqBy1wFd9Bu7bz8M27RuwjL/CrMwtdNOS6ydSh/9FE0L7i2Eh6xNliJN3QJywyixLn4ZmGR80ynDY0ssS0oUzHq8TqF5IGzsWIr1H64Pznn7T+hK0jLSYDNuiPhJEd2bIm/VxbN4bo5dmWQiNb1zW8NmmPDIojeIF/TcWyfBo1EBwUj40AhGM1SLA5RDgzvLhoYPF6AajSQHjbckiOTs29yTzInfgLnPXuno1mhE5bBYngVXby4zzHIPFRKIsJM00nUK6eZJb0OqGQtMiwuI1RjwZrFVqN85zDN6DWmgyRMHGO0AuSaKGvJkWOWde5Bb68iVvaJiWvuNMLISbIU71csgsyQx+GX9YlBUtoyPZ2DJ6PXW/wGXGc8H7NSrUffDwUGMbie299I5ZkBkOirMFlCjnu4W0j5I8SpOop8nEsFk5rTTMov5NgCScuR9q66u0dx4a2S1QybIUPNNdiX3iPBy883mzZuyZWRNCoSexP5Jo1kq8Anav95gzUkZbyy9NCA+EFTJNhoalnbfg1eh0XAg0oqWn1Wgwxnx4ilIiHukEIhiZ+nztRONLjC5ELF5onPW7WA02QcJ5uRCV/mU4K+ejUKBM2OHDw3UbzTZjy866ONx28yIBMQm44RrjC4wuhBEn3EE6FCpQYaUE8Y3IVNzceRsJUuEWKEXhdSJacTrQgj81Udo/hjRdUnH8C0Vfl4ng9cN51vxKo1H/xkqLnIZQNw2gdGpl13zUx8ahWIwNmVpu3t7bgYPLdqHcd5VZml0WboogTvbPOVoiWMRXS0T8odr42tM/I4JnKlq812Fm22J8Gi9BsWWoCIa/rpS6irDgL6vRFukwS7PH2p19CMWSi2DCUeCem/7nnPqFMN3T96MtGiRTkvQYmQiLSJstmxc3vPtdfNJ+wiwdPeveiuJIs6JntclQKOXl9bOgMoGQWYUTsKR8Hnpl2nekwEpiCmnxL9v/MJ468pxZOjJawmdx6/ZjaDjnRL4ruQgmSN1bv2iwJ+hfIwOZ/MdFcFuc+singm8PS72wW2z40Yy7sXrKEjpP4W5MzgY+x5bjO/G31noUuDV4Ox6Eq2M5NAv1lJzMcHDEd1AQrH1y8KeoYYUc85/CXXurMc5doq+JdFBo3xmRe3VhVWXTMOeKWZhRMgnjXCVwWR2IqRK6oj16HOLnf9T2Gf4d9sNjc8PJwuk1mqUHtvBseC6yi6duiYP/LsLP9gc17HnEjYoJgwd5WCHMK43vYNPRl/WFnclfqFR6nESdjisS/crUHY36yGHVeI1VsOizZxNtlLVy1B74bGol9kFQ3PC0PgtrrJyuI7pIJhDWcO9cG9be4jAKBpBQCLOh4XnsPLMHJc7CjMQMZODj030GpYw0O2G429bBEVhM570IRVVUlYt4ec3wH9eTCmGe/mQ7Xj/1LsoynJnRolFgZlOzB2+C8vkTqBivYdfaxN8MUgphdpzejacattHMFOne6v8Fd61TuoQ5xXfgrdueMEuHJy0hzMmOJvzg/Z8iJsfhpQU61rPD66sz2oWHZqzAY7PuM0sTk7aQyzx+eDPeplwr354HB3mbbAtSKN/riYd1U35t/kZUFleYNcnJWAhzMdyGmo+34MDFBuTZPOQ+HRRzBsXWjOAu8AyE4hHk2d14tGoNVk6+y6xNjxEJuYy/txPbT+7CnpYPaBRDFERdlLFaaR1ZKWXgvcTQ2eLX8T+Ftgzc+ZgSpw2SpMeeNVOXYnH5zWbLzBiVkIGc6jyP2tbD+LjtOM51XdDNQ6POshgjjrAI45pn8CrveFSVTsGcK2fjWxNv1M10NGRNyHAEKJKzuXCA5FliJ5HvyNP3NdkF+C8dn/ikO2g+hwAAAABJRU5ErkJggg=="; - ViewRouter.get("/devauth", (req, res) => { - res.send( - GetAuthPage(req.__, "Test 05265", [ - { - name: "Access Profile", - description: - "It allows the application to know who you are. Required for all applications. And a lot of more Text, because why not? This will not stop, till it is multiple lines long and maybe kill the layout, so keep reading as long as you like, but I promise it will get boring after some time. So this should be enougth.", - logo: logo, - }, - { - name: "Test 1", - description: - "This is not an real permission. This is used just to verify the layout", - logo: logo, - }, - { - name: "Test 2", - description: - "This is not an real permission. This is used just to verify the layout", - logo: logo, - }, - ]) - ); - }); -} +ViewRouter.get("/popup", UserMiddleware, (req, res) => { + res.send(GetPopupPage(req.__)); +}); + +// if (config.core.dev) { +// const logo = +// "data:image/png;base64,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"; +// ViewRouter.get("/devauth", (req, res) => { +// res.send( +// GetAuthPage(req.__, "Test 05265", [ +// { +// name: "Access Profile", +// description: +// "It allows the application to know who you are. Required for all applications. And a lot of more Text, because why not? This will not stop, till it is multiple lines long and maybe kill the layout, so keep reading as long as you like, but I promise it will get boring after some time. So this should be enougth.", +// logo: logo, +// }, +// { +// name: "Test 1", +// description: +// "This is not an real permission. This is used just to verify the layout", +// logo: logo, +// }, +// { +// name: "Test 2", +// description: +// "This is not an real permission. This is used just to verify the layout", +// logo: logo, +// }, +// ]) +// ); +// }); +// } export default ViewRouter; diff --git a/views/src/popup/popup.hbs b/views/src/popup/popup.hbs new file mode 100644 index 0000000..d9ccea1 --- /dev/null +++ b/views/src/popup/popup.hbs @@ -0,0 +1,24 @@ + + + + + Popup Auth + + + + + +
+
+

Allow LOADING... to authenticate you?

+
+
+
+ + +
+
+
+ + + diff --git a/views/src/popup/popup.js b/views/src/popup/popup.js new file mode 100644 index 0000000..0e70e44 --- /dev/null +++ b/views/src/popup/popup.js @@ -0,0 +1,32 @@ +async function getJWT(client_id, hostname) { + hostname = encodeURIComponent(hostname); + client_id = encodeURIComponent(client_id); + + const res = await fetch( + `/api/user/jwt?client_id=${client_id}&origin=${hostname}` + ).then((res) => res.json()); + + return res; +} + +let acceptPromise; + +window.allow = () => acceptPromise(); +window.deny = () => window.close(); + +function start() { + let started = false; + window.addEventListener("message", async (msg) => { + if (!started) { + started = true; + const url = new URL(msg.origin); + document.getElementById("hostname").innerText = url.hostname; + await new Promise((yes) => (acceptPromise = yes)); + const res = await getJWT(msg.data.client_id, url.hostname); + msg.source.postMessage(res, msg.origin); + window.close(); + } + }); +} + +start(); diff --git a/views/src/popup/popup.scss b/views/src/popup/popup.scss new file mode 100644 index 0000000..5811b95 --- /dev/null +++ b/views/src/popup/popup.scss @@ -0,0 +1,63 @@ +@import "@material/button/mdc-button"; +.blue-button { + background: #4a89dc !important; +} + +.grey-button { + background: #797979 !important; +} + +hr { + // display: block; + // height: 1px; + border: 0; + border-top: 1px solid #b8b8b8; + // margin: 1em 0; + // padding: 0; +} +body { + font-family: Helvetica; + background: #eee; + -webkit-font-smoothing: antialiased; +} + +.title { + text-align: center; +} + +h1, +h3 { + font-weight: 300; +} + +h1 { + color: #636363; +} + +ul { + list-style: none; + padding-left: 0; +} + +.scope_title { + margin-top: 0; + margin-bottom: 0; + padding-left: 5px; +} + +.scope_description { + margin-top: 0; + padding-left: 15px; + font-size: 13px; + color: #202020; +} + +.card { + max-width: 480px; + margin: 4em auto; + padding: 3em 2em 2em 2em; + background: #fafafa; + border: 1px solid #ebebeb; + box-shadow: rgba(0, 0, 0, 0.14902) 0px 1px 1px 0px, + rgba(0, 0, 0, 0.09804) 0px 1px 2px 0px; +}