Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make a Login with Basic Auth in Kotlin with a GET requet API?

I'm trying to make a Login screen I've made in Android Studio to work with Kotlin but I'm having troubles making a class that will "attach" the Basic Authentication to all the requests. To do this I am using Retrofit2 and OkHttp3.

These are the relevant classes in my code:

GET_LOGIN.kt

package com.joaomartins.srodkitrwale

import okhttp3.OkHttpClient
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Headers

interface GET_LOGIN {
    @GET("login")
    fun getAccessToken() : Call<String>
}

RetrofitClient.kt

package com.joaomartins.srodkitrwale

import android.app.Application
import android.util.Base64
import kotlinx.android.synthetic.main.activity_login.*
import okhttp3.Interceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor

    val username = Login().userTxt.text
    val password = Login().passTxt.text
    val credentials = username + ":" + password
    val AUTH = "Basic " + Base64.encodeToString(credentials.toByteArray(Charsets.UTF_8), Base64.DEFAULT).replace("\n", "")

    val retrofit = RetrofitClient().init()
            //.getBytes(), Base64.DEFAULT).replace("\n", "")
//val AUTH2 = java.util.Base64.getEncoder().encode((username + ":" + password).toByteArray()).toString(Charsets.UTF_8)

class RetrofitClient {
    // Initializing Retrofit
    fun init() : Retrofit{

        // Creating the instance of an Interceptor
        val logging = HttpLoggingInterceptor()
        logging.level = HttpLoggingInterceptor.Level.BODY


        // Creating the OkHttp Builder
        val client = OkHttpClient().newBuilder()


        // Creating the custom Interceptor with Headers
        val interceptor = Interceptor { chain ->
            val request = chain?.request()?.newBuilder()?.addHeader("Authorization", AUTH)?.build()
            chain?.proceed(request)
        }
        client.addInterceptor(interceptor) // Attaching the Interceptor

        // Creating the instance of a Builder
        return Retrofit.Builder()
                .baseUrl("https://srodki.herokuapp.com/")   // The API server
                .client(client.build())                                     // Adding Http Client
                .addConverterFactory(GsonConverterFactory.create()) // Object Converter
                .build()
    }

    fun providesGetLogin(): GET_LOGIN = retrofit.create(GET_LOGIN::class.java)
}

Login.kt

package com.joaomartins.srodkitrwale

import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.util.Base64
import android.util.Log
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_login.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit

class Login : AppCompatActivity() {

    val apiLogin = RetrofitClient().providesGetLogin().getAccessToken()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        loginBtn.setOnClickListener {
            val user = userTxt.text
            val pass = passTxt.text

            if (validateLogin(user, pass)){
                login(user, pass)
            }
        }
    }

    fun validateLogin(user: Editable, pass: Editable): Boolean {
        if (user == null || user.trim().isEmpty()){
            Toast.makeText(this, "Missing Username or Password", Toast.LENGTH_SHORT).show()
            return false
        }
        if (pass == null || pass.trim().isEmpty()){
            Toast.makeText(this, "Missing Username or Password", Toast.LENGTH_SHORT).show()
            return false
        }
        return true
    }

    fun login(user: Editable, pass: Editable) {
        /*val intent = Intent(this, List_users::class.java)
        startActivity(intent)*/
        apiLogin.enqueue(object : Callback<String> {
            override fun onResponse(call: Call<String>, response: Response<String>) {
                Log.d("check", "Reached this place")
                if(!response.isSuccessful)
                    Log.d("failed", "No Success")
                Toast.makeText(this@Login, "Login Successful!", Toast.LENGTH_SHORT).show()
                val intent = Intent(this@Login, List_users::class.java)
                startActivity(intent)
            }

            override fun onFailure(call: Call<String>, t: Throwable) {
                Toast.makeText(this@Login, "Login Failed.", Toast.LENGTH_SHORT).show()
            }
        })

    }

}

The class that would be responsible for the creation of the request with the encrypted authentication is the RetrofitClient class.

I believe the error lies within the following lines of code:

val username = Login().userTxt.text
val password = Login().passTxt.text
val credentials = username + ":" + password
val AUTH = "Basic " + Base64.encodeToString(credentials.toByteArray(Charsets.UTF_8), Base64.DEFAULT).replace("\n", "")

There should be an easier way to do this but I am still learning Android and Kotlin.

like image 595
João Martins Avatar asked Nov 23 '25 12:11

João Martins


1 Answers

Use this:

val client = OkHttpClient()
val credential = Credentials.basic("username", "secret")
val request = Request.Builder()
        .url("https://yourserver.com/api")
        .addHeader("Authorization", credential)
        .build()

client.newCall(request).enqueue(object : Callback{
    override fun onFailure(call: Call, e: IOException) {
        TODO("Not yet implemented")
    }

    override fun onResponse(call: Call, response: Response) {
        println(response.body()?.string())
    }
})
like image 74
Dimitri Schultheis Avatar answered Nov 25 '25 04:11

Dimitri Schultheis