DEV Community

Cover image for First Time Implementing OAuth On X: Thoughts
Sotiris Kourouklis
Sotiris Kourouklis

Posted on • Updated on • Originally published at sotergreco.com

First Time Implementing OAuth On X: Thoughts

After 7 years of development, I have never tried OAuth 1.0 or 2.0. But in the next micro-SaaS I am creating, users will have the option to log in with X. I don't want to add other options for two reasons.

The first is that I like Elon a lot and want to support his platform the best way possible. The second is that when you have multiple login options, sometimes you don't remember which one you used and this has happed a lot to me over the years.

Pre-cooked options

I know that there are options like auth0 but because I want to learn how OAuth works and how the infrastructure is working I decided to implement the whole authentication process myself.

I am using a Kotlin API that has a regular authentication process with JWT. On top of JWT, I want, when the user log in with X, to get their avatar and username and create an account on my application if it does not exist.

Image description

Image description

How OAuth Works

OAuth is basically a 3-step process. You can read the full documentation on X API Docs, but I will cover it briefly to help you understand the process better.

Also keep in mind that OAuth is something like a protocol the process is basically the same in every platform you use with minor differences.

Prerequisites

Each request has some specific headers. Which include the following values:

  • oauth_consumer_key Identifies the application requesting access (get it from developer portal).

  • oauth_nonce (A unique, randomly generated value used to prevent replay attacks - unique token.)

  • oauth_signature (The signature of the request (a cryptographic code ensuring request authenticity create by the other values)

  • oauth_signature_method (The method used to generate the signature e.g., HMAC-SHA1).

  • oauth_timestamp (The current time in seconds to prevent replay attacks).

  • oauth_version (The OAuth version used e.g., OAuth 1.0).

Before I go in more detail, here is a visual representation of how oauth works in my workflow with X.

1st Step

The first step is to get a request token from the X API. That token will help us continue with the other requests

fun requestToken(): String? {
        val client = OkHttpClient()
        val mediaType = "text/plain".toMediaType()
        val body = "".toRequestBody(mediaType)
        val request = Request.Builder()
            .url("https://api.twitter.com/oauth/request_token")
            .post(body)
            .addHeader(
                "Authorization",
                "OAuth oauth_consumer_key=\"KEY\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1716307731\",oauth_nonce=\"NONCE\",oauth_version=\"1.0\",oauth_signature=\"SIGNATURE\""
            )
            .build()
        val response = client.newCall(request).execute()
        val responseString = response.body?.string()
        val oauthToken = responseString?.substringAfter("oauth_token=")?.substringBefore("&")
        return oauthToken
    }
Enter fullscreen mode Exit fullscreen mode

2nd Step

After we have the request token now we can get the verifier from the authorize request.

    @GetMapping("/x/login-redirect")
    fun loginRedirect(): RedirectView {
        val oauthToken = xService.requestToken()
        val redirectView = RedirectView()
        redirectView.url = "https://api.twitter.com/oauth/authorize?oauth_token=$oauthToken"

        return redirectView
    }
Enter fullscreen mode Exit fullscreen mode

3rd Step

The last step is to get the Token with the Secret so we can then move on on getting the user data and finishing our authentication.

Keep in mind the callback is the request the X Api redirect back to when we finish step 2. As a parameter it has the verifier token.

    @GetMapping("/x/callback")
    fun oauth2Callback(
        @RequestParam("oauth_token") oauthToken: String,
        @RequestParam("oauth_verifier") oauthVerifier: String
    ): XCallbackResponse {
        val oauthToken = xService.accessToken(oauthVerifier, oauthToken)

        if (oauthToken.token === "error") {
            throw IllegalStateException("Token is null")
        }
        // your other code
    }
Enter fullscreen mode Exit fullscreen mode

Now with everything finished, we have full access to X's API for the specific user who logged in.

Implementation

As an implementation, it is not very simple; rather, I would say it is complex and difficult. This is why we have OAuth2, which we are going to cover in another article, and it is a lot simpler to understand and implement.

Also, with Kotlin or Spring Boot, there are many libraries you can use that handle the implementation with minimal code by using the default Spring Boot Security Config.

Use Cases

The question is whether it is worth adding OAuth to your application. In my opinion, it is only necessary for B2C products. If you have a B2B application with few daily active users, you don't need to use it.

However, for applications with many users, making the login process simple and fast is very important. If you don't want to add X, you can also try Google, which has a very similar process.

Final Words

Implementing OAuth for the first time can be a challenging but rewarding experience. By choosing to integrate X as your authentication provider, you not only streamline the login process for your users but also gain valuable insights into how OAuth works under the hood.

While the process may seem complex initially, understanding each step and its significance can demystify OAuth and make it more manageable. With this knowledge, you're better equipped to build secure and user-friendly authentication systems for your future projects.

Thanks for reading, and I hope you found this article helpful. If you have any questions, feel free to email me at kourouklis@pm.me, and I will respond.

You can also keep up with my latest updates by checking out my X here: x.com/sotergreco

Top comments (0)