Basic Kotlin/Java + Spring app with GitHub OAuth 2.0
Tags: kotlin, spring, security, github
Published: 2023-04-15 04:58:56

Kotlin and Spring Boot are extremely powerful ecosystems that provide a lot of functionality out of the box.

Authenticating with GitHub OAuth is very easy but it appears that there is a lack of basic guides on how to set one up through OAuth. Believe me, I tried.

(Even GPT sent me down a rabbit hole and I’ve now spent my whole day, debugging and fixing the example it gave — PS: Didn’t work but I learnt enough to build one on my own.) So here goes nothing.

## 5 Steps to Success


### Step 1: Setup your OAuth Application on GitHub

In order to authenticate using GitHub, you need to register an Application on your GitHub account.

- Login to https://github.com. Click on your user settings on the top-right.
- Go to _Settings -> Developer Settings -> OAuth Apps -> New OAuth App_

> Note: If you are authenticating the user for an organization, you must register the application under the organization’s GitHub account and not your personal one.
> The setup for this can be found through:
> _Settings -> Your Organizations -> Select organization -> Settings -> Developer Settings -> OAuth Apps -> New OAuth App_
> 
> You would need to have admin-access to the organization.

- Enter the following details. Hit Register Application. We explain the meaning of the obscure fields next.

![GitHub App Registration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0b4m2yumn8kd4u7prsto.png)

**Homepage URL:** For the purposes of our demo, we will use [http://localhost:8080](http://localhost:8080)

**Authorization Callback URL:** For the purposes of our demo, we will use [http://localhost:8080/login/oauth2/code/github](http://localhost:8080/login/oauth2/code/github)

This URL is the default endpoint that Spring Security uses to receive the authorization code from the GitHub authorization server after the user grants access to your application. The code parameter in the URL indicates that the server is returning an authorization code instead of an access token.

Once Spring Security receives the authorization code, it exchanges it for an access token by sending a token request to the GitHub token endpoint, and uses the access token to authenticate and authorize the user.

> Note: This is the most important step. Frankly, every broken tutorial I found on GitHub OAuth appeared broken because of a mismatch between the value of what they said should be entered here and what they wrote in code. Happens, but be careful so you don’t spend infinite time like I did.

- Hit Register application.
- This will take you to the application settings page. You would need to create a new client secret.
- Note down client secret in a secure place as it will only be displayed only once.
- You would need client id, client secret and the authorization callback url in Step 3 of the tutorial.

### Step 2: Create a new Spring Application
There are many ways to do this. I am using Spring Initializer, which in my opinion is the easiest way specially for those new to Spring framework .

Optionally, you could also create a new Spring project from your IDE and add the dependencies in the gradle or maven project. (code below).

- The easiest way to do this is to use Spring Initializr. I am using Gradle but you can use Maven or Groovy as you like.

- Select Kotlin in the language section. I’m using Spring Boot 3.0.5 with Jar packaging and Java 17. Enter desired package and group names for your project.

- In the Dependencies section, Add “Spring Web” and “OAuth2 Client”.

- Click Generate at the bottom. This will prompt a download in the .zip format. When you unzip, it will create the whole top-level project structure so no need to create a folder before hand. Just unzip and open the project in your favorite IDE.

![Spring Initializr](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bjm9olwrcqwubxrz21in.png)

This step will create the `build.gradle.kts` file for us which would look like this.

```bash
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
 id("org.springframework.boot") version "2.7.10"
 id("io.spring.dependency-management") version "1.0.15.RELEASE"
 kotlin("jvm") version "1.6.21"
 kotlin("plugin.spring") version "1.6.21"
}

group = "com.nsri"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17

repositories {
 mavenCentral()
}

dependencies {
 implementation("org.springframework.boot:spring-boot-starter-oauth2-client")
 implementation("org.springframework.boot:spring-boot-starter-web")
 implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
 implementation("org.jetbrains.kotlin:kotlin-reflect")
 testImplementation("org.springframework.boot:spring-boot-starter-test")
}

tasks.withType<KotlinCompile> {
 kotlinOptions {
  freeCompilerArgs = listOf("-Xjsr305=strict")
  jvmTarget = "17"
 }
}

tasks.withType<Test> {
 useJUnitPlatform()
}
```

This project should build after importing in your IDE.

### Step 3: Create `application.yaml`

Kotlin and Spring Boot often use some default project structure to do default wirings. We will store our settings in the recommended directory as per Spring:

`src/main/resources/application.yaml`

Replace the details in <> below with your client id, client secret and redirect-uri from Step 1.

```yaml
spring:
  security:
    oauth2:
      client:
        registration:
          github:
            client-id: <client-secret-from-github-oauth-setup-step>
            client-secret: <client-secret-from-github-oauth-setup-step>
            redirect-uri: <redirect-uri-from-github-oauth-setup-step> # http://localhost:8080/login/oauth2/code/github
```

If you know how to re-wire Spring to use files from your custom structure using annotations, feel free to add the settings file wherever you usually do.

### Step 4: Create `index.html`

Arguably this is not necessary to demonstrate OAuth or Spring Security but it is nice to have a custom page so you can be sure that authentication worked.

We will store our HTML landing page in `src/main/resources/static/index.html`

```html
<!DOCTYPE html>
<html>
<head>
    <title>Welcome to Demo</title>
</head>
<body>
<h1>Welcome to GitHub OAuth Demo</h1>
</body>
</html>
```

### Step 5: Create `OAuthDemoApplication.kt`

> Note: If you used Spring Initializr or IDE to generate the Spring project, it is likely that it created the main application for you. If so, you can skip to running the project.

Create the main application file under `src/main/kotlin/<package name>/OAuthApplicationDemo.kt` (if it was not already generated).

It should look like this.

```kotlin
package com.nsri.oauthdemo

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication


@SpringBootApplication
class OauthDemoApplication

fun main(args: Array<String>) {
 runApplication<OauthDemoApplication>(*args)
}
```

### You’re done! Run the application

That’s it. As you can see, there is barely any Kotlin specific code here so you can use the same steps for Java as well.

Run your application using `gradle-bootrun` or directly from the IDE.

In your browser, launch [http://localhost:8080](http://localhost:8080)

If you are not authenticated, you will be directed to a page by with Github authentication screen like below. (The url will redirect to Github). Enter your credentials (including 2FA) to login as usual.


![GitHub Authorization Page on localhost:8080](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ucdyf8qawp5t0yumnqql.png)

After login, you will be taken to index.html.


![Welcome Page (index.html)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qk32zk9vs3pki2a34kv5.png)

If you are already authenticated in this browser session, you will be directly taken to `index.html`. This is expected (and honestly the point of OAuth2.0) because it is a type of “Single Sign-On”, which means it remembers your login if you have already authenticated.

For testing purposes, use a private/incognito window of your browser or clear browser history and cookies and launch `localhost:8080` again.

All done! 🎉

Hope you found this tutorial helpful and it saved you some time.

(All the code is available on the oauth-demo repository on [Github](https://github.com/neha-sri/oauth-demo).)