The Simplest Way to Authorize Github OAuth Apps with Next.js and Cotter
Putri Karunia
Posted on September 8, 2020
Add "Sign in with Github" in one click to authorize your Github OAuth App and access Github REST API using Cotter and Next.js.
Cotter just launched a Github Login integration 🎉. This means you can easily log your users in and get an access token to enable Github integrations in your app.
What we're building
We're going to build a website with Next.js that allows your users to login with email or with Github and get a list of their public and private repositories.
Overview
- Let's Start - Make our Home Page
- Let's see how this works before moving on to Github API
- Designing our API endpoints to get data from Github
- Showing the Repo List in our Dashboard Page
- But, what if the user didn't Sign in with Github?
Let's Start – Make our Home Page
Create your Next.js project
Start with creating a new Next.js project by running the code below, and follow the instructions.
yarn create next-app
Add a Login Form in the Home Page
We're using Cotter for the Login form to quickly enable an Email Magic Link login and Sign in with Github.
Add Cotter as a dependency
yarn add cotter
Add a Login Form and a Title
Modify our home page at pages/index.js
. We'll start with the simple Email Magic Link login. Remove everything in pages/index.js
and add a title and Cotter's login form:
You'll need an API_KEY_ID
, create a new project, and copy the API_KEY_ID
from the dashboard. The code above should give you a simple Login page that looks like this:
Enable Github Login
The documentation laid out the steps you need to take to enable Social Login to your login form. We'll follow it step by step below:
First, create a Github OAuth App. Summarizing Github's documentation, you should do the following:
- Click on your profile picture on the top right > Settings > Developer Settings > OAuth Apps > New OAuth App
- Fill in your Application Name, Homepage URL, and description based on your app.
- Fill in
https://www.cotter.app/api/v0/oauth/token/callback/GITHUB
for the Authorization callback URL. - Then click Register Application.
Go to your Cotter Dashboard and add a Social Login connection.
Go to Dashboard > Social Login > New Login Connection > Github. Then copy your Client ID and Client Secret from Github. We'll add the repo
scope because we want to get the users' repository data.
Press Create to create the login connection.
Show Github Login on your Form
Now that your Social Login connection is set up, we can show it in our Login Form. Go to Dashboard > Branding > Magic Link. Check the box for Github under Social Login Providers.
Press Save to update your customization.
You should now see the Sign in with Github button in our Next.js app.
Let's see how this works before moving on to Github API
We'll go over how the login works, how you can authenticate users to your backend, and how you can get Github's access token to access private repo data.
1. Let's try logging in with your email address first.
Enter your email address and press "Sign in Without Password". Tap the magic link in your email and you should be logged-in.
Now check your console log, you should see something like this:
{
"token": {...},
"email": "team@cotter.app", // 👈 the user's email
"oauth_token": {
"access_token": "eyJhbGciOiJFUzI...", // 👈 access token
"id_token": "eyJhbGciOiJFUzI1...",
"refresh_token": "236:QDVxW6...",
"expires_in": 3600,
"token_type": "Bearer",
"auth_method": "OTP"
},
"user": {
"ID": "abcdefgh-abcd-abcd-9959-67ebae3cdfcf", // 👈 user ID
"issuer": "abcdefgh-abcd-abcd-81ad-5cc8b69051e8",
"identifier": "team@cotter.app",
...
}
}
Note: If your console log can't be expanded because you redirected to
/dashboard
, comment out the redirection partrouter.push("/dashboard")
Three things that you should take note of are the user's email , the Cotter User ID, and the access_token that we will use to protect our API endpoints. These information will be available to you at anytime the user is logged-in by calling cotter.tokenHandler.getAccessToken()
and cotter.getLoggedInUser()
2. Let's try logging-in again but with your Github account that has the same email address
When you used a Github account that has the same address as an existing account, you should see a prompt asking if you'd like to link the accounts:
If you're using a Github account that has an email address that is not recognized, then it will automatically create a new user. You'll see the same JSON response like the above when the user has successfully log in with Github.
Designing our API endpoints to get data from Github
- We will have a dashboard page that will call our API endpoint at
/api/repo
to get a list of repositories owned by the user. - We'll make an API endpoint
/api/repo
that will:
- Check if the user is logged-in
- If logged-in, get the user's Github Access Token from Cotter's API
- Call Github API to get the authenticated user's repository list
Make our API endpoint at /api/repo
Our endpoint will look like this:
GET http://localhost:3000/api/repo
Authorization: Bearer <Cotter Access Token>
1. Make a function to handle API calls to /api/repo
Next.js gives you a neat way to add server code that can handle API requests. To handle an API call to /api/repo
, make a file pages/api/repo.js
. Then, we'll add a skeleton handler function with a list of things that we need to do:
2. Check if the Authorization Header have a valid access token
We'll make a separate function above our handler
function to do this check. We'll be using Cotter's client library to help us validate the access token.
yarn add cotter-node
What we did was pretty simple:
- First, we check if the Authorization header exists
- If it exists, then we check if the
access_token
is valid using Cotter's helper function. - Then we call
checkJWT(handler)
to run the check and then run the handler if the check passed.
3. Get the Cotter User ID from the access_token
.
We will need this for our API call to Cotter. The access_token
is a JWT token that contains the user's Cotter User ID. Check here for the full spec. We'll use another Cotter helper function to parse the access token and get the Cotter User ID.
yarn add cotter-token-js
4. Get Github Access Token from Cotter API
The API to get a Social Provider access token from Cotter looks like this
curl -XGET \
-H 'API_KEY_ID: <COTTER API KEY ID>' \
-H 'API_SECRET_KEY: <COTTER API SECRET KEY>' \
'https://www.cotter.app/api/v0/oauth/token/GITHUB/<COTTER USER ID>'
Let's install axios and create our request
yarn add axios
As you can see we're storing our secrets in an environment variable. Get your API_KEY_ID
and API_SECRET_KEY
from the dashboard and export it in your terminal, then run yarn dev
.
$ export COTTER_API_KEY_ID=<API KEY ID>
$ export COTTER_API_SECRET_KEY=<API SECRET KEY>
$ yarn dev
5. Call Github API to get the repositories list
Github's API to get the list of repositories of the authenticated user looks like this:
curl \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token <GITHUB ACCESS TOKEN>" \
"https://api.github.com/user/repos"
Let's make the request using axios and the Github Access Token that we get in the earlier step.
That's it, let's try our API endpoint
Copy your access token from the console log when logging in and run:
curl \
-H "Authorization: Bearer <COTTER ACCESS TOKEN>" \
"http://localhost:3000/api/repo"
You should see the following response:
Showing the Repo List in our Dashboard Page
Make the Dashboard Page
Add a dashboard page by making a file at pages/dashboard.js
. Using useEffect
we will call our API endpoint to get the repositories, and put the results in our React state:
Let's go over what we did:
- We added 2 React states,
err
andrepos
, to show errors and the repo data. - When the component mounts, we call
getRepositories
which first gets the user's access token using Cotter's functioncotter.tokenHandler.getAccessToken()
, then calls an API request to our backend endpoint at/api/repo
. - When the API call is successful, the function will update our
repos
state with the list of repositories, or show an error.
If you sign-in with Github, then go to localhost:3000/dashboard
, you'll see the following:
Don't forget to uncomment the redirection part in
/pages/index.js
:router.push("/dashboard")
Add a NavBar to Log Out or Log In and navigate between pages
Let's add a Navbar component to help our users navigate our website. Make a file /components/Navbar/index.js
in your project directory.
- We added a
loggedIn
andemail
state. If the user is logged-in, we'll display the Log Out button and the user's email, otherwise we'll display the Login button. - The function
checkLoggedIn
will check if the user is logged in and update theloggedIn
state and set the user'semail
state - We also added a function called
logOut
to log out the user.
Make the checkLoggedIn
function
We can do this using Cotter's function by checking if an access token exists. Update your checkLoggedIn
function:
Make the logOut
function
We can also do this by calling Cotter's cotter.logOut()
function. Update your logOut
function:
Import the Navbar in your Home Page and Dashboard Page
In /pages/index.js
:
In /pages/dashboard.js
:
Great! Now our website works well and users can log in/log out and get their Repositories list.
But, what if the user didn't Sign in with Github?
If the user didn't Sign in with Github, then we wouldn't get Github's Access Token, and it will return an error like this:
How do we fix this?
Fortunately, Cotter has a function to allow logged-in users to Connect a Github Account of their choosing to their current account. This means we can add a button in the dashboard that tells the user to Connect Github if we get this error.
Add a button to Connect Github if not connected yet.
Following the guide to Connect a Github account to an Existing User, we'll add a function and a button at pages/dashboard.js
Now let's try logging in with an email that is not associated with your Github account using the Email Address
field. You should see something like this:
Press Connect Github , and it will connect your currently logged-in Github Account with this email address.
If you log out and log in again with Github, you will now be logged-in to this new email address.
How do I disconnect a Github Account
We won't cover this in the tutorial, but you can use our API endpoint to delete a connection.
That's it!
We now have a working Github API integration with a simple way to get your user's Github Access Token.
What's Next?
There's a lot of things that you can do using Github's API.
- Check out the complete list of Github's REST API here.
- See the code for this tutorial in our Github repo.
Questions & Feedback
Come and talk to the founders of Cotter and other developers who are using Cotter on Cotter's Slack Channel.
Ready to use Cotter?
If you enjoyed this tutorial and want to integrate Cotter into your website or app, you can create a free account and check out our documentation.
If you need help, ping us on our Slack channel or email us at team@cotter.app.
Posted on September 8, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
September 8, 2020