{"id":2572,"date":"2022-06-08T17:56:52","date_gmt":"2022-06-08T17:56:52","guid":{"rendered":"https:\/\/codevoweb.com\/?p=2572"},"modified":"2023-01-22T20:21:53","modified_gmt":"2023-01-22T20:21:53","slug":"github-oauth-authentication-vue-and-node","status":"publish","type":"post","link":"https:\/\/codevoweb.com\/github-oauth-authentication-vue-and-node\/","title":{"rendered":"GitHub OAuth Authentication Vue.js and Node.js (No Passport)"},"content":{"rendered":"\n<p>This article will teach you how to implement GitHub OAuth Authentication with <a href=\"https:\/\/vuejs.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Vue.js<\/a> and Node.js without Passport.js. <\/p>\n\n\n\n<p>Also, after the user is authenticated, we&#8217;ll return JWT access and refresh token cookies to the user&#8217;s browser or client.<\/p>\n\n\n\n<p>Related Articles:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/github-oauth-authentication-vue-and-node\">GitHub OAuth Authentication Vue.js and Node.js (No Passport)<\/a><\/li>\n\n\n\n<li><a href=\"\/google-oauth-authentication-react-and-node\">Google OAuth Authentication React.js and Node.js(No Passport)<\/a><\/li>\n\n\n\n<li><a href=\"\/github-oauth-authentication-react-and-node\">GitHub OAuth Authentication React.js and Node.js(No Passport)<\/a><\/li>\n\n\n\n<li><a href=\"\/how-to-implement-github-oauth-in-reactjs\">How to Implement GitHub OAuth in React.js<\/a><\/li>\n\n\n\n<li><a href=\"\/how-to-implement-google-oauth2-in-reactjs\">How to Implement Google OAuth2 in React.js<\/a><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"850\" height=\"478\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-Authentication-Vue.js-and-Node.js-No-Passport.webp\" alt=\"GitHub OAuth Authentication Vue.js and Node.js (No Passport)\" class=\"wp-image-2614\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-Authentication-Vue.js-and-Node.js-No-Passport.webp 850w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-Authentication-Vue.js-and-Node.js-No-Passport-300x169.webp 300w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-Authentication-Vue.js-and-Node.js-No-Passport-768x432.webp 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-Authentication-Vue.js-and-Node.js-No-Passport-100x56.webp 100w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-Authentication-Vue.js-and-Node.js-No-Passport-700x394.webp 700w\" sizes=\"auto, (max-width: 850px) 100vw, 850px\" \/><\/figure>\n\n\n<style>.kb-table-of-content-nav.kb-table-of-content-id_701b39-5b .kb-table-of-content-wrap{padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;border-color:#abb8c3;border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;}.kb-table-of-content-nav.kb-table-of-content-id_701b39-5b .kb-table-of-contents-title-wrap{padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;}.kb-table-of-content-nav.kb-table-of-content-id_701b39-5b .kb-table-of-contents-title-wrap{color:#ffffff;}.kb-table-of-content-nav.kb-table-of-content-id_701b39-5b .kb-table-of-contents-title{color:#ffffff;font-weight:regular;font-style:normal;}.kb-table-of-content-nav.kb-table-of-content-id_701b39-5b .kb-table-of-content-wrap .kb-table-of-content-list{color:#ffffff;font-weight:regular;font-style:normal;margin-top:10px;margin-right:0px;margin-bottom:0px;margin-left:-5px;}<\/style>\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Basic knowledge of HTML, CSS, Vue.js and Golang is need.<\/li>\n\n\n\n<li>You should have Golang installed on your computer.<\/li>\n<\/ul>\n\n\n\n<span id=\"ezoic-pub-video-placeholder-17\"><\/span>\n\n\n\n<h2 class=\"wp-block-heading\">Create an OAuth App on GitHub<\/h2>\n\n\n\n<p>First, you need to log into your <a href=\"https:\/\/github.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub<\/a> account, and at the top-right corner, click on the Profile icon and select <strong>&#8220;Settings&#8221;<\/strong>.<\/p>\n\n\n\n<p>On the profile page, scroll to the bottom, and from the left-sidebar click <strong>&#8220;Developer settings&#8221;<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"622\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-click-on-the-developer-settings-1024x622.png\" alt=\"GitHub OAuth with react and node click on the developer settings\" class=\"wp-image-2258\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-click-on-the-developer-settings-1024x622.png 1024w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-click-on-the-developer-settings-300x182.png 300w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-click-on-the-developer-settings-768x466.png 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-click-on-the-developer-settings-100x61.png 100w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-click-on-the-developer-settings-700x425.png 700w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-click-on-the-developer-settings.png 1151w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Now, select <strong>OAuth Apps<\/strong> on the Developer settings page and click on the <strong>&#8220;New OAuth App&#8221;<\/strong> button on the right side.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"594\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-developer-settings-1024x594.png\" alt=\"GitHub OAuth with react and node developer settings\" class=\"wp-image-2259\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-developer-settings-1024x594.png 1024w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-developer-settings-300x174.png 300w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-developer-settings-768x446.png 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-developer-settings-100x58.png 100w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-developer-settings-700x406.png 700w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-developer-settings.png 1125w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, provide the necessary information about the OAuth app and click on the <strong>&#8220;Register application&#8221;<\/strong> button.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The authorization callback URL should point to a route on your server. It&#8217;s similar to the <a href=\"https:\/\/codevoweb.com\/google-oauth-authentication-vue-and-node\">Google OAuth implementation<\/a> in the previous article.<\/p>\n<\/blockquote>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"715\" height=\"921\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-register-application.png\" alt=\"GitHub OAuth with react and node register application\" class=\"wp-image-2263\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-register-application.png 715w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-register-application-233x300.png 233w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-register-application-78x100.png 78w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-register-application-349x450.png 349w\" sizes=\"auto, (max-width: 715px) 100vw, 715px\" \/><\/figure>\n\n\n\n<p>Next, click on the <strong>&#8220;Generate a new client secret&#8221;<\/strong> button to generate the secret key after GitHub has successfully created the OAuth app.<\/p>\n\n\n\n<p>Don&#8217;t be alarmed when GitHub redirects you to provide your password again.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"853\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-create-credentials-1024x853.png\" alt=\"GitHub OAuth with react and node create credentials\" class=\"wp-image-2261\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-create-credentials-1024x853.png 1024w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-create-credentials-300x250.png 300w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-create-credentials-768x640.png 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-create-credentials-100x83.png 100w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-create-credentials-540x450.png 540w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-create-credentials.png 1127w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Edit the <code>.env<\/code> file in your server folder and add the client ID, client secret, and the authorization callback URL.<\/p>\n\n\n\n<p><strong>.env<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-js\"><code>\nGITHUB_OAUTH_CLIENT_ID=your client Id here\nGITHUB_OAUTH_CLIENT_SECRET=your client secret here\nGITHUB_OAUTH_REDIRECT_URL=http:\/\/localhost:8000\/api\/sessions\/oauth\/github\n<\/code>\n<\/pre>\n\n\n\n<p>Also, remember to update the <code>.env.local<\/code> file in the Vue.js app.<\/p>\n\n\n\n<pre class=\"line-numbers language-js\"><code>\nVITE_GITHUB_OAUTH_CLIENT_ID=your client Id here\nVITE_GITHUB_OAUTH_CLIENT_SECRET=your client secret here\nVITE_GITHUB_OAUTH_REDIRECT_URL=http:\/\/localhost:8000\/api\/sessions\/oauth\/github\n<\/code>\n<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Note: use <code>Vue_App_<\/code> prefix if you generated the app with the <code>@vue\/cli<\/code> .<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Generate the Consent Screen URL<\/h2>\n\n\n\n<p>Now, we are ready to add GitHub OAuth Authentication to our Vue.js application.<\/p>\n\n\n\n<p>First, we need to generate the GitHub OAuth consent screen URL based on the client ID, scopes, and the authorization callback URL.<\/p>\n\n\n\n<p>The scopes give us read access to specific resources on the GitHub API. In this mini-app, we are only interested the user&#8217;s email address.<\/p>\n\n\n\n<p>Feel free to play around with the different scopes to better understand how to use them.<\/p>\n\n\n\n<p><strong>src\/utils\/getGithubUrl.js<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-js\"><code>\nexport function getGitHubUrl(from) {\n  const rootURl = 'https:\/\/github.com\/login\/oauth\/authorize';\n\n  const options = {\n    client_id: import.meta.env.VITE_GITHUB_OAUTH_CLIENT_ID,\n    redirect_uri: import.meta.env.VITE_GITHUB_OAUTH_REDIRECT_URL,\n    scope: 'user:email',\n    state: from,\n  };\n\n  const qs = new URLSearchParams(options);\n\n  return `${rootURl}?${qs.toString()}`;\n}\n<\/code>\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Build a Simple GitHub OAuth Button with Vue.js<\/h2>\n\n\n\n<p>Now let&#8217;s create a simple GitHub OAuth button with Vue.js.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"877\" height=\"1024\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/github-oauth-with-vuejs-and-nodejs-877x1024.png\" alt=\"github oauth with vuejs and nodejs\" class=\"wp-image-2588\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/github-oauth-with-vuejs-and-nodejs-877x1024.png 877w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/github-oauth-with-vuejs-and-nodejs-257x300.png 257w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/github-oauth-with-vuejs-and-nodejs-768x897.png 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/github-oauth-with-vuejs-and-nodejs-86x100.png 86w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/github-oauth-with-vuejs-and-nodejs-385x450.png 385w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/github-oauth-with-vuejs-and-nodejs.png 925w\" sizes=\"auto, (max-width: 877px) 100vw, 877px\" \/><\/figure>\n\n\n\n<p><strong><strong>src\/App.vue<\/strong><\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-html\"><code>\n&lt;script setup&gt;\nimport GoogleLogo from '.\/assets\/google.svg';\nimport GitHubLogo from '.\/assets\/github.svg';\nimport { getGoogleUrl } from '.\/utils\/getGoogleUrl';\nimport { getGitHubUrl } from '.\/utils\/getGitHubUrl';\n\nconst from = '\/';\n&lt;\/script&gt;\n\n&lt;template&gt;\n  &lt;div class=\"container\"&gt;\n    &lt;div class=\"social-auth\"&gt;\n      &lt;!-- Google OAuth --&gt;\n      &lt;a :href=\"getGoogleUrl(from)\" class=\"auth-btn google-auth\"&gt;\n        &lt;img :src=\"GoogleLogo\" alt=\"Google Logo\" \/&gt;\n        &lt;span&gt;Google&lt;\/span&gt;\n      &lt;\/a&gt;\n      &lt;!-- GitHub OAuth --&gt;\n      &lt;a :href=\"getGitHubUrl(from)\" class=\"auth-btn github-auth\"&gt;\n        &lt;img :src=\"GitHubLogo\" alt=\"GitHub Logo\" \/&gt;\n        &lt;span&gt;Google&lt;\/span&gt;\n      &lt;\/a&gt;\n    &lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/template&gt;\n\n&lt;style&gt;\n* {\n  margin: 0;\n  padding: 0;\n  box-sizing: border-box;\n}\na {\n  text-decoration: none;\n  color: inherit;\n}\n\nhtml {\n  font-size: 62.5%;\n}\n\nbody {\n  font-family: Roboto, sans-serif;\n  color: #222;\n  font-size: 1.6rem;\n}\n\n.container {\n  background-color: #2363eb;\n  height: 100vh;\n  width: 100vw;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n.social-auth {\n  max-width: 27rem;\n  width: 100%;\n  display: flex;\n  align-items: center;\n  flex-direction: column;\n}\n\n.auth-btn {\n  background-color: #fff;\n  border-radius: 5px;\n  padding: 0.6rem 0;\n  width: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  transition: all 0.3s ease-in-out;\n}\n\n.auth-btn img {\n  height: 4rem;\n  margin-right: 1rem;\n}\n.auth-btn span {\n  font-size: 1.8rem;\n}\n\n.auth-btn:hover {\n  box-shadow: 0 1px 13px 0 rgb(0 0 0 \/ 15%);\n}\n\n.auth-btn.google-auth {\n  margin-bottom: 1.5rem;\n}\n&lt;\/style&gt;\n\n<\/code>\n<\/pre>\n\n\n\n<p>Next, click on the GitHub Oauth button and you should be taken to the GitHub consent screen.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"796\" height=\"833\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-consent-screen.png\" alt=\"GitHub OAuth with react and node consent screen\" class=\"wp-image-2270\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-consent-screen.png 796w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-consent-screen-287x300.png 287w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-consent-screen-768x804.png 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-consent-screen-96x100.png 96w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-consent-screen-430x450.png 430w\" sizes=\"auto, (max-width: 796px) 100vw, 796px\" \/><\/figure>\n\n\n\n<p>Click on the green <strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-black-color\">Authorize<\/mark><\/strong> button on the GitHub consent screen or log in with your email and password if you haven&#8217;t done that.<\/p>\n\n\n\n<p>A <strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">404 error<\/mark><\/strong> should be returned by your NodeJs server assuming the server is running. <\/p>\n\n\n\n<p>The important part of the authorization callback URL is the code in the query string. We&#8217;ll later use the code to obtain the access token on the server.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"929\" height=\"1024\" src=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-error-route-not-implemented-929x1024.png\" alt=\"GitHub OAuth with react and node error route not implemented\" class=\"wp-image-2271\" srcset=\"https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-error-route-not-implemented-929x1024.png 929w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-error-route-not-implemented-272x300.png 272w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-error-route-not-implemented-768x847.png 768w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-error-route-not-implemented-91x100.png 91w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-error-route-not-implemented-408x450.png 408w, https:\/\/codevoweb.com\/wp-content\/uploads\/2022\/06\/GitHub-OAuth-with-react-and-node-error-route-not-implemented.png 953w\" sizes=\"auto, (max-width: 929px) 100vw, 929px\" \/><\/figure>\n\n\n\n<p>The server returned a <strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">404 error<\/mark><\/strong> because we haven&#8217;t implemented the GitHub OAuth logic on the server yet.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implement GitHub OAuth on the Server<\/h2>\n\n\n\n<p>Now, run the following command in the terminal to install the <a href=\"https:\/\/axios-http.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Axios<\/a> package. The <a href=\"https:\/\/axios-http.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Axios<\/a> package will enable us to make HTTP requests to the GitHub API.<\/p>\n\n\n\n<pre class=\"line-numbers language-shell\"><code>\nyarn add axios\n<\/code>\n<\/pre>\n\n\n\n<p>Update the <code>config\/custom-environment-variables.ts<\/code> file to have the GitHub OAuth client Id, client secret, and the authorization callback URL.<\/p>\n\n\n\n<p><strong>config\/custom-environment-variables.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-js\"><code>\nexport default {\n  dbName: 'MONGODB_USERNAME',\n  dbPass: 'MONGODB_PASSWORD',\n  \n  accessTokenPrivateKey: 'ACCESS_TOKEN_PRIVATE_KEY',\n  accessTokenPublicKey: 'ACCESS_TOKEN_PUBLIC_KEY',\n  refreshTokenPrivateKey: 'REFRESH_TOKEN_PRIVATE_KEY',\n  refreshTokenPublicKey: 'REFRESH_TOKEN_PUBLIC_KEY',\n\n  googleClientId: 'GOOGLE_OAUTH_CLIENT_ID',\n  googleClientSecret: 'GOOGLE_OAUTH_CLIENT_SECRET',\n  googleOauthRedirect: 'GOOGLE_OAUTH_REDIRECT_URL',\n\n  githubClientId: 'GITHUB_OAUTH_CLIENT_ID',\n  githubClientSecret: 'GITHUB_OAUTH_CLIENT_SECRET',\n  githubOauthRedirect: 'GITHUB_OAUTH_REDIRECT_URL',\n};\n<\/code>\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Retrieve the GitHub OAuth Access Token and User&#8217;s Profile<\/h3>\n\n\n\n<p>Add these two functions to the <code>session.service.ts<\/code> file in the services folder.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>getGithubOathToken()<\/code> &#8211; To obtain the OAuth Access Token from GitHub<\/li>\n\n\n\n<li><code>getGithubUser()<\/code>  &#8211; To retrieve the user&#8217;s profile data with the Access Token<\/li>\n<\/ul>\n\n\n\n<p>Below are the functions to retrieve the GitHub access token and the user&#8217;s profile data:<\/p>\n\n\n\n<p><strong>src\/services\/session.service.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\n\/\/ ? GitHub OAuth\n\ntype GitHubOauthToken = {\n  access_token: string;\n};\n\ninterface GitHubUser {\n  login: string;\n  id: number;\n  node_id: string;\n  avatar_url: string;\n  gravatar_id: string;\n  url: string;\n  html_url: string;\n  followers_url: string;\n  following_url: string;\n  gists_url: string;\n  starred_url: string;\n  subscriptions_url: string;\n  organizations_url: string;\n  repos_url: string;\n  events_url: string;\n  received_events_url: string;\n  type: string;\n  site_admin: boolean;\n  name: string;\n  company: string;\n  blog: string;\n  location: null;\n  email: string;\n  hireable: boolean;\n  bio: string;\n  twitter_username: string;\n  public_repos: number;\n  public_gists: number;\n  followers: number;\n  following: number;\n  created_at: Date;\n  updated_at: Date;\n}\n\nexport const getGithubOathToken = async ({\n  code,\n}: {\n  code: string;\n}): Promise&lt;GitHubOauthToken&gt; =&gt; {\n  const rootUrl = 'https:\/\/github.com\/login\/oauth\/access_token';\n  const options = {\n    client_id: config.get&lt;string&gt;('githubClientId'),\n    client_secret: config.get&lt;string&gt;('githubClientSecret'),\n    code,\n  };\n\n  const queryString = qs.stringify(options);\n\n  try {\n    const { data } = await axios.post(`${rootUrl}?${queryString}`, {\n      headers: {\n        'Content-Type': 'application\/x-www-form-urlencoded',\n      },\n    });\n\n    const decoded = qs.parse(data) as GitHubOauthToken;\n\n    return decoded;\n  } catch (err: any) {\n    throw Error(err);\n  }\n};\n\nexport const getGithubUser = async ({\n  access_token,\n}: {\n  access_token: string;\n}): Promise&lt;GitHubUser&gt; =&gt; {\n  try {\n    const { data } = await axios.get&lt;GitHubUser&gt;(\n      'https:\/\/api.github.com\/user',\n      {\n        headers: {\n          Authorization: `Bearer ${access_token}`,\n        },\n      }\n    );\n\n    return data;\n  } catch (err: any) {\n    throw Error(err);\n  }\n};\n<\/code>\n<\/pre>\n\n\n\n<p>Complete code consisting of Google and GitHub OAuth implementation logic:<\/p>\n\n\n\n<p><strong>src\/services\/session.service.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\nimport config from 'config';\nimport axios from 'axios';\nimport qs from 'qs';\n\ninterface GoogleOauthToken {\n  access_token: string;\n  id_token: string;\n  expires_in: number;\n  refresh_token: string;\n  token_type: string;\n  scope: string;\n}\n\nexport const getGoogleOauthToken = async ({\n  code,\n}: {\n  code: string;\n}): Promise&lt;GoogleOauthToken&gt; =&gt; {\n  const rootURl = 'https:\/\/oauth2.googleapis.com\/token';\n\n  const options = {\n    code,\n    client_id: config.get&lt;string&gt;('googleClientId'),\n    client_secret: config.get&lt;string&gt;('googleClientSecret'),\n    redirect_uri: config.get&lt;string&gt;('googleOauthRedirect'),\n    grant_type: 'authorization_code',\n  };\n  try {\n    const { data } = await axios.post&lt;GoogleOauthToken&gt;(\n      rootURl,\n      qs.stringify(options),\n      {\n        headers: {\n          'Content-Type': 'application\/x-www-form-urlencoded',\n        },\n      }\n    );\n\n    return data;\n  } catch (err: any) {\n    console.log('Failed to fetch Google Oauth Tokens');\n    throw new Error(err);\n  }\n};\n\ninterface GoogleUserResult {\n  id: string;\n  email: string;\n  verified_email: boolean;\n  name: string;\n  given_name: string;\n  family_name: string;\n  picture: string;\n  locale: string;\n}\n\nexport async function getGoogleUser({\n  id_token,\n  access_token,\n}: {\n  id_token: string;\n  access_token: string;\n}): Promise&lt;GoogleUserResult&gt; {\n  try {\n    const { data } = await axios.get&lt;GoogleUserResult&gt;(\n      `https:\/\/www.googleapis.com\/oauth2\/v1\/userinfo?alt=json&amp;access_token=${access_token}`,\n      {\n        headers: {\n          Authorization: `Bearer ${id_token}`,\n        },\n      }\n    );\n\n    return data;\n  } catch (err: any) {\n    console.log(err);\n    throw Error(err);\n  }\n}\n\n\/\/ ? GitHub OAuth\n\ntype GitHubOauthToken = {\n  access_token: string;\n};\n\ninterface GitHubUser {\n  login: string;\n  id: number;\n  node_id: string;\n  avatar_url: string;\n  gravatar_id: string;\n  url: string;\n  html_url: string;\n  followers_url: string;\n  following_url: string;\n  gists_url: string;\n  starred_url: string;\n  subscriptions_url: string;\n  organizations_url: string;\n  repos_url: string;\n  events_url: string;\n  received_events_url: string;\n  type: string;\n  site_admin: boolean;\n  name: string;\n  company: string;\n  blog: string;\n  location: null;\n  email: string;\n  hireable: boolean;\n  bio: string;\n  twitter_username: string;\n  public_repos: number;\n  public_gists: number;\n  followers: number;\n  following: number;\n  created_at: Date;\n  updated_at: Date;\n}\n\nexport const getGithubOathToken = async ({\n  code,\n}: {\n  code: string;\n}): Promise&lt;GitHubOauthToken&gt; =&gt; {\n  const rootUrl = 'https:\/\/github.com\/login\/oauth\/access_token';\n  const options = {\n    client_id: config.get&lt;string&gt;('githubClientId'),\n    client_secret: config.get&lt;string&gt;('githubClientSecret'),\n    code,\n  };\n\n  const queryString = qs.stringify(options);\n\n  try {\n    const { data } = await axios.post(`${rootUrl}?${queryString}`, {\n      headers: {\n        'Content-Type': 'application\/x-www-form-urlencoded',\n      },\n    });\n\n    const decoded = qs.parse(data) as GitHubOauthToken;\n\n    return decoded;\n  } catch (err: any) {\n    throw Error(err);\n  }\n};\n\nexport const getGithubUser = async ({\n  access_token,\n}: {\n  access_token: string;\n}): Promise&lt;GitHubUser&gt; =&gt; {\n  try {\n    const { data } = await axios.get&lt;GitHubUser&gt;(\n      'https:\/\/api.github.com\/user',\n      {\n        headers: {\n          Authorization: `Bearer ${access_token}`,\n        },\n      }\n    );\n\n    return data;\n  } catch (err: any) {\n    throw Error(err);\n  }\n};\n\n<\/code>\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">User Model<\/h3>\n\n\n\n<p>If you came from a previous tutorial in this series then update the <code>user.model.ts<\/code> file to have the <code>provider<\/code> field.<\/p>\n\n\n\n<p>When a user creates an account with GitHub OAuth, we&#8217;ll set the <code>provider<\/code> field to <code>GitHub<\/code> whereas a user who registers with email and password will have the <code>provider<\/code> to be <code>local<\/code> .<\/p>\n\n\n\n<p><strong>src\/models\/user.model.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\nimport {\n  DocumentType,\n  getModelForClass,\n  index,\n  modelOptions,\n  pre,\n  prop,\n} from '@typegoose\/typegoose';\nimport bcrypt from 'bcryptjs';\n\n@index({ email: 1 })\n@pre&lt;User&gt;('save', async function () {\n  \/\/ Hash password if the password is new or was updated\n  if (!this.isModified('password')) return;\n\n  \/\/ Hash password with costFactor of 12\n  this.password = await bcrypt.hash(this.password, 12);\n})\n@modelOptions({\n  schemaOptions: {\n    \/\/ Add createdAt and updatedAt fields\n    timestamps: true,\n  },\n})\n\n\/\/ Export the User class to be used as TypeScript type\nexport class User {\n  @prop()\n  name: string;\n\n  @prop({ unique: true, required: true })\n  email: string;\n\n  @prop({ required: true, minlength: 8, maxLength: 32, select: false })\n  password: string;\n\n  @prop({ default: 'user' })\n  role: string;\n\n  @prop({ default: 'default.png' })\n  photo: string;\n\n  @prop({ default: false })\n  verified: boolean;\n\n  @prop({ default: 'local' })\n  provider: string;\n\n  \/\/ Instance method to check if passwords match\n  async comparePasswords(hashedPassword: string, candidatePassword: string) {\n    return await bcrypt.compare(candidatePassword, hashedPassword);\n  }\n}\n\n\/\/ Create the user model from the User class\nconst userModel = getModelForClass(User);\nexport default userModel;\n<\/code>\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Service to Upsert the User<\/h3>\n\n\n\n<p>Now, add this service function to enable us to upsert the user&#8217;s information in the MongoDB database.<\/p>\n\n\n\n<p><strong>src\/services\/user.service.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\nexport const findAndUpdateUser = async (\n  query: FilterQuery&lt;User&gt;,\n  update: UpdateQuery&lt;User&gt;,\n  options: QueryOptions\n) =&gt; {\n  return await userModel.findOneAndUpdate(query, update, options);\n};\n<\/code>\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Create the GitHub OAuth Controller<\/h3>\n\n\n\n<p>Next, let&#8217;s create a <code>githubOauthHandler<\/code> function in the <code>auth.controller.ts<\/code> file. This controller will be evoked when GitHub redirects the user to the server.<\/p>\n\n\n\n<p><strong>src\/controllers\/auth.controller.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\nexport const githubOauthHandler = async (\n  req: Request,\n  res: Response,\n  next: NextFunction\n) =&gt; {\n  try {\n    \/\/ Get the code from the query\n    const code = req.query.code as string;\n    const pathUrl = (req.query.state as string) ?? '\/';\n\n    if (req.query.error) {\n      return res.redirect(`${config.get&lt;string&gt;('origin')}\/login`);\n    }\n\n    if (!code) {\n      return next(new AppError('Authorization code not provided!', 401));\n    }\n\n    \/\/ Get the user the access_token with the code\n    const { access_token } = await getGithubOathToken({ code });\n\n    \/\/ Get the user with the access_token\n    const { email, avatar_url, login } = await getGithubUser({ access_token });\n\n    \/\/ Create new user or update user if user already exist\n    const user = await findAndUpdateUser(\n      { email },\n      {\n        email,\n        photo: avatar_url,\n        name: login,\n        provider: 'GitHub',\n        verified: true,\n      },\n      { runValidators: false, new: true, upsert: true }\n    );\n\n    if (!user) {\n      return res.redirect(`${config.get&lt;string&gt;('origin')}\/oauth\/error`);\n    }\n\n    \/\/ Create access and refresh tokens\n    const { access_token: accessToken, refresh_token } = await signToken(user);\n\n    res.cookie('access_token', accessToken, accessTokenCookieOptions);\n    res.cookie('refresh_token', refresh_token, refreshTokenCookieOptions);\n    res.cookie('logged_in', true, {\n      ...accessTokenCookieOptions,\n      httpOnly: false,\n    });\n\n    res.redirect(`${config.get&lt;string&gt;('origin')}${pathUrl}`);\n  } catch (err: any) {\n    return res.redirect(`${config.get&lt;string&gt;('origin')}\/oauth\/error`);\n  }\n};\n<\/code>\n<\/pre>\n\n\n\n<p>In the above code, you&#8217;ll notice that when we called the <code>findAndUpdateUser<\/code> service we defined above, we added <code>upsert: true<\/code> in the query options.<\/p>\n\n\n\n<p>Adding <code>upsert: true<\/code> will instruct Mongoose to create the user if the email used in the query doesn&#8217;t exist in the database. On the other hand, Mongoose will only update the user&#8217;s credentials if that email already exists in the database.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Create the Route<\/h3>\n\n\n\n<p>Edit the <code>session.routes.ts<\/code> file and add the GitHub OAuth handler.<\/p>\n\n\n\n<p><strong>src\/routes\/session.routes.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\nimport express from 'express';\nimport { googleOauthHandler,githubOauthHandler } from '..\/controllers\/auth.controller';\n\nconst router = express.Router();\n\nrouter.get('\/oauth\/google', googleOauthHandler);\nrouter.get('\/oauth\/github', githubOauthHandler);\n\nexport default router;\n<\/code>\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Add the Router To the Middleware Stack<\/h3>\n\n\n\n<p>Finally, add the session router defined above to the Express middleware stack in the <code>src\/app.ts<\/code> file.<\/p>\n\n\n\n<p><strong>src\/app.ts<\/strong><\/p>\n\n\n\n<pre class=\"line-numbers language-ts\"><code>\nimport sessionRouter from '.\/routes\/session.route';\n\n\/\/ ? Register the session router\napp.use('\/api\/sessions', sessionRouter);\n<\/code>\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Congrats for reaching the end. In this article, you learned how to add GitHub OAuth to a Node.js and MongoDB application without using Passport.<\/p>\n\n\n\n<p>You can find the complete code used in this <a href=\"https:\/\/github.com\/wpcodevo\/vue_auth\/tree\/vue-auth-github\" target=\"_blank\" rel=\"noopener\">tutorial on GitHub<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article will teach you how to implement GitHub OAuth Authentication with Vue.js and Node.js without Passport.js. Also, after the user is authenticated, we&#8217;ll return&#8230;<\/p>\n","protected":false},"author":1,"featured_media":2614,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[74],"tags":[42,73],"class_list":["post-2572","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-vue","tag-nodejs-api","tag-vuejs"],"acf":[],"_links":{"self":[{"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/posts\/2572","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/comments?post=2572"}],"version-history":[{"count":1,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/posts\/2572\/revisions"}],"predecessor-version":[{"id":10144,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/posts\/2572\/revisions\/10144"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/media\/2614"}],"wp:attachment":[{"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/media?parent=2572"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/categories?post=2572"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codevoweb.com\/wp-json\/wp\/v2\/tags?post=2572"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}