How to use Github OAuth in your app like a pro.

How to use Github OAuth in your app like a pro.

Would you like to have a Sign-In with GitHub button on your Web App, well here is how you can achieve that with Github OAuth.

OAuth is an open standard protocol for authorization. It is a way your users grant you permission to access their GitHub information without giving you their passwords.
Trust me when I say, that is the best thing a user will ever want to encounter. Not having to create passwords or go through any email verification.

With OAuth, a user can create one account on a website and link his/her information to every other website. It's easier and better than creating a username, passwords, etc for every website they visit.
That is the way most users prefer it to other options.

There are several companies with OAuth, but some of the most popular are Google, Facebook, Twitter, Apple, GitHub, etc...

Though they are different companies with different ways of handling their authorization, the principle is the same i.e

  1. Create an OAuth app with the company
  2. Use your app's id/secret to get a token for a user.
  3. Access the company's API to access the user's information.

There may be further steps in between, but trust me; it's simple. What I'd recommend is going over the company's documentation to know what is and what isn't.

For Facebook, for example, its long-lived token will expire after 60 days whereas that of GitHub doesn't. So make sure you study and understand the documentation.

Creating a sign-in system with any of the companies listed above is so easy that you don't need PassportJS or Firebase Authentication or any other. It's just easy.

So let's dive right into one which is GitHub.

What are the things you need for GitHub's OAuth?

  1. A GitHub account (personal or organization).
  2. An OAuth Application.
  3. Your app secret and id.
  4. A token to access GitHub's API.

1: Creating an OAuth Application.

Am assuming you already have a GitHub account. If you haven't, head on to www.github.com to get started.

If your account is all set up, now you can decide if you're going to use an organization account or a personal account. For production, it is best to use an organization account. I will use my personal account for this.

  1. Go to your Settings
  2. Scroll down and click Developer Settings
  3. Click OAuth Apps
  4. Click New OAuth App.

The next steps require your application name, homepage URL, application description, and authorization callback URL.

The authorization callback URL is the URL GitHub will redirect to after a user authorized your app. You can use your localhost URL and a path to handle the callback for now. Like http://localhost:5000/callback

2: Your App's ID and Secret

Click on the OAuth app you just created, and you will see your App's ID as Client ID and secret as Client Secrets. Copy them and paste them somewhere safe in your app.

3: OAuth Token

NOTE: OAuth token varies for users, no two users have the same token.

The steps below will direct you on how to get a token for a user.

How it Works

  1. Users click the Sign-In with GitHub button on your website and are redirected to GitHub.
  2. The users authorize your app on GitHub's website and are redirected back to your website.
  3. The callback URL has a code as a query that you will use to exchange a token.
  4. Use the token to access GitHub's API and user information.

Step 1: Redirect users to GitHub
With the front-end, we will redirect users to GitHub's OAuth page. To do that we need our client id and a state.

A state is an unguessable random string that is sent to Github. In the callback URL, Github sends that state back. Such that you can verify that it is the state you sent to Github that was sent back to you. Just to make sure authorization wasn't compromised.

href="https://github.com/login/oauth/authorize?client_id={client_id}&state={state}"

Don't forget to replace the client_id and state with yours.
If you are using a template engine or something, you may want to use the express redirect:

app.get('/', (req, res) => {
  res.redirect('https://github.com/login/oauth/authorize?client_id={client_id}&state={state}');
})

Which one you use doesn't really matter, as long as it successfully redirects and displays GitHub login.

There are other query parameters that you should check out. One that I would like to mention here is scopes. This is common with all OAuth.

It is the way of letting the authorization company know the information of this user you want to access. It also covers the things that you would want to do on behalf of that user.

These permissions are usually displayed when a user is about to authorize your app. Here is the list of GitHub's scope

To get the basic read-only information of a user, like an email, name, id, repositories, organizations, etc we don't need to declare a scope for GitHub.

I have worked on a link generator with all scopes in GitHub, some in Google, all in Facebook, and all in Discord.

With the app, you can select the scopes you want and a link will be generated, which should make it easy for you, I guess. Will be out in a few days.

Step 2: Exchange Code for Token
The callback URL you used earlier while creating your OAuth app is what GitHub will redirect users to if they (users) authorize your app.

The URL contains a temporal code (to expire after 10 minutes) and your state (from step 1). What you need this code for is to exchange it for a user access token.

Exchanging the code for a token should be done on your server. With express and Axios would be

app.get('/:code', async (req, res) => {
  const { code } = req.params;
  const response = await axios.post(
      'https://github.com/login/oauth/access_token',
      {
        client_id: config.get('client_id'),
        client_secret: config.get('client_secret'),
        code,
      },
      {
        headers: {
          Accept: 'application/json', // for a json response from github
        },
      }
    );

    console.log(response.data.access_token)
})

I used the config package to hide my client_id and client_secret just in case of publishing to GitHub. You should do the same.

Step 3: Access GitHub's API
In this app, all we want is the user's basic information i.e name, username, email, id, and avatar URL. We will use the access token to access the API.

const response = await axios.get('https://api.github.com/user', {
 headers: {
  Authorization: token ${token}, }, });

Replace the token with the user's token. For the above-listed information we want from the user, destructuring the response will be thus

const { login: username, email, id, avatar_url, name } = response.data; 

Username is represented as login in github api.

That is basically how you make a sign-in system with GitHub. But you may face a bit of challenge when working this out for production.

For example, it is not recommended that you have any API secrets in your client (React precisely), not even with .env. So how would you handle this?

Another example could be with the token, how and where should you store a user's token. Or how you should verify a token is valid. Because if a token is not valid, Github's API is not going to return any user.

GitHub OAuth in a React App.

This is going to be an app with react as the front-end and express at the back-end. We will make it very practical, it is how I did mine. So follow along.

How it will work

  1. The client (our front-end) requests the App's id (client_id) from the server (our back-end)
  2. The client redirects to the Github OAuth page with our client_id.
  3. Github redirects back to the client's callback URL with a code
  4. Client sends this code to the server.
  5. Server exchanges the code for a token.
  6. Server verifies token to be valid, logs in the user, and send the token to the client
  7. Client stores the token in cookies.

GitHub OAuth

The reason for the first step is this, you can't use a secret in the front-end (react specifically). You will not be able to hide it. Not even with .env.

Clearly, you can scrap step one out, because client_id is not sensitive in this case. But this should give you an idea of what you should do when using an API secret in the front-end.

I believe this is clear enough. If you want to see how I used this check out the source code on Github.

Conclusion

This procedure is similar to all other OAuth offered by other companies.

If you find this useful, you can support me with just $5 monthly on Patreon. It means a lot. Thank you and happy hacking.

Elijah_trillionz

I am Elijah, a full-stack web developer with a passion for sharing knowledge.

Leave a Reply