{"id":18317900,"url":"https://github.com/idiocc/github","last_synced_at":"2025-04-09T13:51:16.799Z","repository":{"id":57117508,"uuid":"202927048","full_name":"idiocc/github","owner":"idiocc","description":"The GitHub OAuth Flow For Idio Web Server.","archived":false,"fork":false,"pushed_at":"2020-02-27T13:29:47.000Z","size":143,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-16T18:34:15.698Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://idio.cc","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/idiocc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-08-17T20:09:36.000Z","updated_at":"2020-02-27T13:29:50.000Z","dependencies_parsed_at":"2022-08-22T16:50:25.759Z","dependency_job_id":null,"html_url":"https://github.com/idiocc/github","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fgithub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fgithub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fgithub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fgithub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/idiocc","download_url":"https://codeload.github.com/idiocc/github/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248054218,"owners_count":21039951,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T18:07:49.185Z","updated_at":"2025-04-09T13:51:16.778Z","avatar_url":"https://github.com/idiocc.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @idio/github\n\n[![npm version](https://badge.fury.io/js/%40idio%2Fgithub.svg)](https://www.npmjs.com/package/@idio/github)\n\n`@idio/github` is The GitHub OAuth Flow For the [Idio Web Server](https://github.com/idiocc/idio).\n\n```sh\nyarn add @idio/github\n```\n\n## Table Of Contents\n\n- [Table Of Contents](#table-of-contents)\n- [API](#api)\n- [`githubOAuth(app, config): void`](#githuboauthapp-_goaapplicationconfig-githuboauthconfig-void)\n  * [`GithubOAuthConfig`](#type-githuboauthconfig)\n  * [`GithubEmail`](#type-githubemail)\n- [Copyright](#copyright)\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/0.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## API\n\nThe package is available by importing its default function:\n\n```js\nimport github from '@idio/github'\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/1.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n\n## \u003ccode\u003e\u003cins\u003egithubOAuth\u003c/ins\u003e(\u003c/code\u003e\u003csub\u003e\u003cbr/\u003e\u0026nbsp;\u0026nbsp;`app: _goa.Application,`\u003cbr/\u003e\u0026nbsp;\u0026nbsp;`config: !GithubOAuthConfig,`\u003cbr/\u003e\u003c/sub\u003e\u003ccode\u003e): \u003ci\u003evoid\u003c/i\u003e\u003c/code\u003e\nThe GitHub OAuth Login Routes For The Idio Web Server. Two routes will be configured: one to redirect to GitHub to start authentication, and one to handle the callback from GitHub. They will be installed on the app automatically.\n\n - \u003ckbd\u003e\u003cstrong\u003eapp*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e\u003ca href=\"https://github.com/idiocc/goa/wiki/Application#type-application\" title=\"The application interface.\"\u003e_goa.Application\u003c/a\u003e\u003c/code\u003e\u003c/em\u003e: The Goa/Koa Application.\n - \u003ckbd\u003e\u003cstrong\u003econfig*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e\u003ca href=\"#type-githuboauthconfig\" title=\"Options for the program.\"\u003e!GithubOAuthConfig\u003c/a\u003e\u003c/code\u003e\u003c/em\u003e: Options for the middleware.\n\n__\u003ca name=\"type-githuboauthconfig\"\u003e`GithubOAuthConfig`\u003c/a\u003e__: Options for the program.\n\u003ctable\u003e\n \u003cthead\u003e\u003ctr\u003e\n  \u003cth\u003eName\u003c/th\u003e\n  \u003cth\u003eType \u0026amp; Description\u003c/th\u003e\n  \u003cth\u003eDefault\u003c/th\u003e\n \u003c/tr\u003e\u003c/thead\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eclient_id*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e-\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   The app's client id.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eclient_secret*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e-\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   The app's client secret.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003epath\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003e/auth/github\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   The server path to start the login flaw at.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eredirectPath\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e-\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   The redirect path (must start with \u003ccode\u003e/\u003c/code\u003e). If not specified, \u003ccode\u003e${path}/redirect\u003c/code\u003e will be used.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003escope\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e-\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   The scope to ask permissions for. No scope by default.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003esession\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e\u003ca href=\"https://github.com/idiocc/goa/wiki/Application#middlewarectx-contextnext-function-promisevoid\" title=\"The function to handle requests which can be installed with the `.use` method.\"\u003e!_goa.Middleware\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e-\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   The configured session middleware in case the \u003ccode\u003esession\u003c/code\u003e property is not globally available on the context.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003efinish\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(ctx: \u003ca href=\"https://github.com/idiocc/idio/wiki/Home#type-context\" title=\"The extension to the standard Goa context with properties set by middleware.\"\u003eContext\u003c/a\u003e, token: string, scope: string, user: \u003ca href=\"#type-githubuser\" title=\"Public user information\"\u003e!GithubUser\u003c/a\u003e, next: function()) =\u003e !Promise\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   The function to complete the authentication that receives the token and the data about the user, such as name and id. The default function redirects to \u003ccode\u003e/\u003c/code\u003e.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003ectx*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e\u003ca href=\"https://github.com/idiocc/idio/wiki/Home#type-context\" title=\"The extension to the standard Goa context with properties set by middleware.\"\u003eContext\u003c/a\u003e\u003c/code\u003e\u003c/em\u003e: The app context.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003etoken*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003estring\u003c/code\u003e\u003c/em\u003e: The exchanged token.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003escope*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003estring\u003c/code\u003e\u003c/em\u003e: The scopes which the user authorised the app to access.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003euser*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e\u003ca href=\"#type-githubuser\" title=\"Public user information\"\u003e!GithubUser\u003c/a\u003e\u003c/code\u003e\u003c/em\u003e: The scopes which the user authorised the app to access.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003enext*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003efunction()\u003c/code\u003e\u003c/em\u003e: Calls next middleware.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eerror\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(ctx: \u003ca href=\"https://github.com/idiocc/idio/wiki/Home#type-context\" title=\"The extension to the standard Goa context with properties set by middleware.\"\u003e!Context\u003c/a\u003e, error: string, description: string, next: function()) =\u003e !Promise\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   The function to be called in case of error. If not specified, the middleware will throw an internal server error.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003ectx*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e\u003ca href=\"https://github.com/idiocc/idio/wiki/Home#type-context\" title=\"The extension to the standard Goa context with properties set by middleware.\"\u003e!Context\u003c/a\u003e\u003c/code\u003e\u003c/em\u003e: The app context.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003eerror*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003estring\u003c/code\u003e\u003c/em\u003e: The error type.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003edescription*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003estring\u003c/code\u003e\u003c/em\u003e: The explanation of the error.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003enext*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003efunction()\u003c/code\u003e\u003c/em\u003e: Calls next middleware.\n  \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n\n```jsx\nimport github from '..'\nimport idio from '@idio/idio'\n\nconst Server = async () =\u003e {\n  const { url, app, router, middleware: {\n    session,\n  } } = await idio({\n    session: {\n      keys: [process.env.SESSION_KEY],\n    },\n  })\n\n  router.get('/', session, (ctx) =\u003e {\n    ctx.body = render(\u003chtml\u003e\n      \u003cbody\u003e\n        {ctx.session.user ?\n          \u003cspan\u003eHello, {ctx.session.user}.{' '}\n            \u003ca href=\"/signout\"\u003eSign Out\u003c/a\u003e\n          \u003c/span\u003e :\n          \u003ca href=\"/github\"\u003eSign In With GitHub\u003c/a\u003e}\n        \u003chr/\u003e\n        (c) Art Deco, 2020\n      \u003c/body\u003e\n    \u003c/html\u003e, { addDoctype: true })\n  })\n  router.get('/signout', session, (ctx) =\u003e {\n    ctx.session = null\n    ctx.redirect('/')\n  })\n  app.use(router.routes())\n\n  github(app, {\n    session,\n    client_id: process.env.CLIENT_ID,\n    client_secret: process.env.CLIENT_SECRET,\n    scope: 'user:email',\n    error(ctx, error) {\n      ctx.redirect(`/?error=${error}`)\n    },\n    path: '/github',\n    async finish(ctx, token, scope, user, next) {\n      console.log(user.name, user.login, user.company)\n      ctx.session.user = user.login\n      ctx.session.manuallyCommit()\n      ctx.redirect('/')\n    },\n  })\n  return { app, url }\n}\n```\n```\n[+] CLIENT_ID [+] CLIENT_SECRET [+] SESSION_KEY \nhttp://localhost:5000 \n{\n  body: 'Redirecting to \u003ca href=\"https://www.github.com/login/oauth/authorize?client_id=f0a8762e7329780e85de\u0026amp;redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Fgithub%2Fredirect\u0026amp;state=8275\u0026amp;scope=user%3Aemail\"\u003ehttps://www.github.com/login/oauth/authorize?client_id=f0a8762e7329780e85de\u0026amp;redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Fgithub%2Fredirect\u0026amp;state=8275\u0026amp;scope=user%3Aemail\u003c/a\u003e.',\n  headers: {\n    'set-cookie': [\n      'koa:sess=eyJnaXRoaWItc3RhdGUiOjgyNzUsIl9leHBpcmUiOjE1ODI4OTY0NTk1OTIsIl9tYXhBZ2UiOjg2NDAwMDAwfQ==; path=/; expires=Fri, 28 Feb 2020 13:27:39 GMT; httponly',\n      'koa:sess.sig=mPZuFR0kFz8XFkQRJeuTm3VnMfw; path=/; expires=Fri, 28 Feb 2020 13:27:39 GMT; httponly'\n    ],\n    location: 'https://www.github.com/login/oauth/authorize?client_id=f0a8762e7329780e85de\u0026redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Fgithub%2Fredirect\u0026state=8275\u0026scope=user%3Aemail',\n    'content-type': 'text/html; charset=utf-8',\n    'content-length': '391',\n    date: 'Thu, 27 Feb 2020 13:27:39 GMT',\n    connection: 'close'\n  },\n  statusCode: 302,\n  statusMessage: 'Found'\n}\n\n \u003e Redirect to Dialog https://www.github.com/login/oauth/authorize?client_id=f0a8762e7329780e85de\u0026redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Fgithub%2Fredirect\u0026state=8275\u0026scope=user%3Aemail\n```\n\nIf authorisation was successful, the server will make a request to GitHub API at `/user` path with the token, to get user's public info. This information can then be accessed in the `finish` function passed in the config.\n\nIf the `user:email` scope was requested, emails returned from the `/user/emails` API path will also be populated in the `emails` field. If the user's main email is private, it won't be visible in the `email` field, so that this scope should be requested if the email address needs to be collected.\n\n__\u003ca name=\"type-githubemail\"\u003e`GithubEmail`\u003c/a\u003e__\n\u003ctable\u003e\n \u003cthead\u003e\u003ctr\u003e\n  \u003cth\u003eName\u003c/th\u003e\n  \u003cth\u003eType \u0026amp; Description\u003c/th\u003e\n \u003c/tr\u003e\u003c/thead\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eemail*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   The email address.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003everified*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Whether the email was verified.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eprimary*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Whether the email is primary.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003evisibility*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Either \u003ccode\u003epublic\u003c/code\u003e or \u003ccode\u003eprivate\u003c/code\u003e.\n  \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n\n\n__\u003ca name=\"type-githubuser\"\u003e`GithubUser`\u003c/a\u003e__: Public user information\n\u003ctable\u003e\n \u003cthead\u003e\u003ctr\u003e\n  \u003cth\u003eName\u003c/th\u003e\n  \u003cth\u003eType \u0026amp; Description\u003c/th\u003e\n \u003c/tr\u003e\u003c/thead\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eemail*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e?string\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Publicly visible email address. \u003ccode\u003eoctocat＠github.com\u003c/code\u003e or \u003ccode\u003enull\u003c/code\u003e.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eemails*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e!Array\u0026lt;\u003ca href=\"#type-githubemail\"\u003e!GithubEmail\u003c/a\u003e\u0026gt;\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   All email addresses accessible if the \u003ccode\u003euser:email\u003c/code\u003e scope was requested.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003elogin*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003eoctocat\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eid*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003enumber\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   1\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003enode_id*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003eMDQ6VXNlcjE=\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eavatar_url*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003ehttps://github.com/images/error/octocat_happy.gif\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003egravatar_id*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003e\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eurl*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003ehttps://api.github.com/users/octocat\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003ehtml_url*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003ehttps://github.com/octocat\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003efollowers_url*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003ehttps://api.github.com/users/octocat/followers\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003efollowing_url*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003ehttps://api.github.com/users/octocat/following{/other_user}\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003egists_url*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003ehttps://api.github.com/users/octocat/gists{/gist_id}\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003estarred_url*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003ehttps://api.github.com/users/octocat/starred{/owner}{/repo}\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003esubscriptions_url*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003ehttps://api.github.com/users/octocat/subscriptions\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eorganizations_url*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003ehttps://api.github.com/users/octocat/orgs\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003erepos_url*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003ehttps://api.github.com/users/octocat/repos\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eevents_url*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003ehttps://api.github.com/users/octocat/events{/privacy}\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003ereceived_events_url*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003ehttps://api.github.com/users/octocat/received_events\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003etype*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003eUser\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003esite_admin*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   false\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003ename*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003emonalisa octocat\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003ecompany*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003eGitHub\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eblog*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003ehttps://github.com/blog\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003elocation*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003eSan Francisco\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003ehireable*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   false\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003ebio*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003eThere once was...\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003epublic_repos*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003enumber\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   2\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003epublic_gists*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003enumber\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   1\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003efollowers*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003enumber\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   20\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003efollowing*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003enumber\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   0\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003ecreated_at*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003e2008-01-14T04:33:35Z\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eupdated_at*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003estring\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ccode\u003e2008-01-14T04:33:35Z\u003c/code\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n\nA custom implementation of the  `finish` function can be provided, only that `session` must be manually committed after being set.\n\n```js\n/**\n * @param {!_idio.Context} ctx\n * @param {string} token\n * @param {string} scope\n * @param {!_idio.GithubUser} user\n */\nexport const defaultFinish = async (ctx, token, scope, user, next) =\u003e {\n  ctx.session['token'] = token\n  ctx.session['scope'] = scope\n  ctx.session['user'] = user\n  await ctx.session.manuallyCommit()\n  ctx.redirect('/')\n}\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/2.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Copyright\n\nGNU Affero General Public License v3.0\n\nAffero GPL means that you're not allowed to use this middleware on the web unless you release the source code for your application. This is a restrictive license which has the purpose of defending Open Source work and its creators.\n\nPlease refer to the [Idio license agreement](https://github.com/idiocc/idio#copyright--license) for more info on dual-licensing. You're allowed to use this middleware without disclosing the source code if you sign up on the [neoluddite.dev](https://neoluddite.dev) package reward scheme.\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth\u003e\n      \u003ca href=\"https://www.artd.eco\"\u003e\n        \u003cimg width=\"100\" src=\"https://raw.githubusercontent.com/wrote/wrote/master/images/artdeco.png\"\n          alt=\"Art Deco\"\u003e\n      \u003c/a\u003e\n    \u003c/th\u003e\n    \u003cth\u003e© \u003ca href=\"https://www.artd.eco\"\u003eArt Deco™\u003c/a\u003e for \u003ca href=\"https://idio.cc\"\u003eIdio\u003c/a\u003e 2020\u003c/th\u003e\n    \u003cth\u003e\n      \u003ca href=\"https://idio.cc\"\u003e\n        \u003cimg src=\"https://avatars3.githubusercontent.com/u/40834161?s=100\" width=\"100\" alt=\"Idio\"\u003e\n      \u003c/a\u003e\n    \u003c/th\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/-1.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidiocc%2Fgithub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fidiocc%2Fgithub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidiocc%2Fgithub/lists"}