diff --git a/.env.local.sample b/.env.local.sample new file mode 100644 index 0000000..bb1a700 --- /dev/null +++ b/.env.local.sample @@ -0,0 +1,3 @@ +GITHUB_CALLBACK_BASE_URL=http://localhost:3000 +GITHUB_CLIENT_ID= +GITHUB_CLIENT_SECRET= diff --git a/.gitignore b/.gitignore index c87c9b3..65eb910 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,7 @@ yarn-error.log* .pnpm-debug.log* # local env files -.env*.local +.env.local # vercel .vercel diff --git a/README.md b/README.md index ff4f460..4ac05d0 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,28 @@ A directory of Nation3 Citizens and their profiles +## Environment Variables + +### GitHub + +How to create a new OAuth App: + +1. Go to https://github.com/organizations/nation3/settings/applications + +1. Click "New OAuth App" + + - Application name: Nation3 Citizen Directory + + - Homepage URL: https://nation3.org + + - Authorization callback URL: https://citizens.nation3.org + +Add the environment variables to `.env.local`: + +``` +cp .env.local.sample .env.local +``` + ## Build ``` diff --git a/package.json b/package.json index 87e6292..4978235 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,10 @@ "daisyui": "^2.13.5", "ethers": "^5.7.0", "next": "12.2.5", + "next-connect": "^0.13.0", "papaparse": "^5.3.2", + "passport": "^0.6.0", + "passport-github2": "^0.1.12", "react": "^18.2.0", "react-blockies": "^1.4.1", "react-chartjs-2": "^4.3.1", diff --git a/pages/[passportId]/auth/github.tsx b/pages/[passportId]/auth/github.tsx new file mode 100644 index 0000000..c882b3f --- /dev/null +++ b/pages/[passportId]/auth/github.tsx @@ -0,0 +1,13 @@ +import { NextPage } from "next" + +const GitHubPage: NextPage = () => { + console.info('GitHubPage') + + return ( + <> + [ Connect GitHub ] + + ) +} + +export default GitHubPage diff --git a/pages/api/[passportId]/auth/github-callback.ts b/pages/api/[passportId]/auth/github-callback.ts new file mode 100644 index 0000000..4b32814 --- /dev/null +++ b/pages/api/[passportId]/auth/github-callback.ts @@ -0,0 +1,21 @@ +import nc from "next-connect" +const passport = require('passport') + +const failurePath = `/233/auth/github` // TODO: get [passportId] +console.info('failurePath:', failurePath) + +// Handle GitHub response +const handler = nc() + .get( + passport.authenticate('github', { + failureRedirect: failurePath + }), + (req, res) => { + // Successful authentication, redirect to /[passportId]/auth/github-success + // TODO + console.info('req:', req) + console.info('res:', res) + } + ) + +export default handler diff --git a/pages/api/[passportId]/auth/github.ts b/pages/api/[passportId]/auth/github.ts new file mode 100644 index 0000000..9d0e4d0 --- /dev/null +++ b/pages/api/[passportId]/auth/github.ts @@ -0,0 +1,36 @@ +import nc from "next-connect" +const passport = require('passport') +const GitHubStrategy = require('passport-github2').Strategy + +const callbackBaseUrl = process.env['GITHUB_CALLBACK_BASE_URL'] +console.info('callbackBaseUrl:', callbackBaseUrl) + +const callbackUrl = `${callbackBaseUrl}/api/233/auth/github-callback` // TODO: get [passportId] +console.info('callbackUrl:', callbackUrl) + +// Configure strategy +passport.use(new GitHubStrategy( + { + clientID: process.env['GITHUB_CLIENT_ID'], + clientSecret: process.env['GITHUB_CLIENT_SECRET'], + callbackURL: callbackUrl + }, + function(accessToken: any, refreshToken: any, profile: any, done: any) { + console.info('accessToken:', accessToken) + console.info('refreshToken:', refreshToken) + console.info('profile:', profile) + console.info('profile.username:', profile.username) + console.info('done:', done) + return done(null, profile) + } +)) + +// Redirect to GitHub authentication +const handler = nc() + .get( + passport.authenticate('github', { + scope: ['user:email'] + }) + ) + +export default handler diff --git a/yarn.lock b/yarn.lock index 3b8bfd7..6518dbc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1278,6 +1278,11 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +base64url@3.x.x: + version "3.0.1" + resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" + integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== + bech32@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" @@ -3063,6 +3068,13 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +next-connect@^0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/next-connect/-/next-connect-0.13.0.tgz#dff835d2f5eab1f65503dae747dfef23c43020f0" + integrity sha512-f2G4edY01XomjCECSrgOpb/zzQinJO6Whd8Zds0+rLUYhj5cLwkh6FVvZsQCSSbxSc4k9nCwNuk5NLIhvO1gUA== + dependencies: + trouter "^3.2.0" + next@12.2.5: version "12.2.5" resolved "https://registry.yarnpkg.com/next/-/next-12.2.5.tgz#14fb5975e8841fad09553b8ef41fe1393602b717" @@ -3121,6 +3133,11 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== +oauth@0.9.x: + version "0.9.15" + resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" + integrity sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA== + object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -3250,6 +3267,38 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +passport-github2@^0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/passport-github2/-/passport-github2-0.1.12.tgz#a72ebff4fa52a35bc2c71122dcf470d1116f772c" + integrity sha512-3nPUCc7ttF/3HSP/k9sAXjz3SkGv5Nki84I05kSQPo01Jqq1NzJACgMblCK0fGcv9pKCG/KXU3AJRDGLqHLoIw== + dependencies: + passport-oauth2 "1.x.x" + +passport-oauth2@1.x.x: + version "1.6.1" + resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.6.1.tgz#c5aee8f849ce8bd436c7f81d904a3cd1666f181b" + integrity sha512-ZbV43Hq9d/SBSYQ22GOiglFsjsD1YY/qdiptA+8ej+9C1dL1TVB+mBE5kDH/D4AJo50+2i8f4bx0vg4/yDDZCQ== + dependencies: + base64url "3.x.x" + oauth "0.9.x" + passport-strategy "1.x.x" + uid2 "0.0.x" + utils-merge "1.x.x" + +passport-strategy@1.x.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" + integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== + +passport@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" + integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + utils-merge "^1.0.1" + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -3280,6 +3329,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pause@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" + integrity sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg== + pbkdf2@^3.0.17: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" @@ -3534,6 +3588,11 @@ regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" +regexparam@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/regexparam/-/regexparam-1.3.0.tgz#2fe42c93e32a40eff6235d635e0ffa344b92965f" + integrity sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g== + regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" @@ -3926,6 +3985,13 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +trouter@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/trouter/-/trouter-3.2.0.tgz#a9c510fce21b8e659a28732c9de9d82871efe8df" + integrity sha512-rLLXbhTObLy2MBVjLC+jTnoIKw99n0GuJs9ov10J870vDw5qhTurPzsDrudNtBf5w/CZ9ctZy2p2IMmhGcel2w== + dependencies: + regexparam "^1.3.0" + tsconfig-paths@^3.14.1: version "3.14.1" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" @@ -3982,6 +4048,11 @@ typescript@4.7.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== +uid2@0.0.x: + version "0.0.4" + resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.4.tgz#033f3b1d5d32505f5ce5f888b9f3b667123c0a44" + integrity sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA== + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" @@ -4035,6 +4106,11 @@ util@^0.12.4: is-typed-array "^1.1.3" which-typed-array "^1.1.2" +utils-merge@1.x.x, utils-merge@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"