Android| Basic Auth using retrofit2 and local API

ZookKep :

I started making an app and connected it to a mock API at first. Now I want to connect it an API that runs on my PC.

For starters, I'm trying to implement the login access. Since my API's base URL was http://localhost:5000/energy/api/ I changed it to http://<< MyIPAddress >>:5000/energy/api/ (don't know if this is right yet). I'm testing it on my actual phone. But with my code username and password are passed on as parameters, while I'd like to login with basic auth (this is how I do it in Postman). For example this is how I want the authentication to be done: enter image description here

But with my code I get this: enter image description here

This is my Request Manager:

object RequestManager {
    val interceptor = HttpLoggingInterceptor()
    val client = OkHttpClient.Builder().addInterceptor(interceptor).build()
    init {
        interceptor.level = HttpLoggingInterceptor.Level.BODY
    }

    val retrofit = Retrofit.Builder()
        .baseUrl("http://<<MYIP>>:5000/energy/api/")
        .addConverterFactory(GsonConverterFactory.create())
        .client(client)
        .build()

    val service = retrofit.create(Api::class.java)

My MainActivity.kt:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        login_button.setOnClickListener {
            buttonClicked()
        }

        if (getTokenFromPrefs()?.length!! > 0) {
            openSearchActivity()
        }
    }

    private fun buttonClicked() {
        val username = username_edittext.text.toString()
        val password = password_edittext.text.toString()
        Log.d("eeee","button clicked " + username_edittext.text.toString() + " password "+password_edittext.text.toString() )

        val call = RequestManager.service.login(username, password)
        call.enqueue(object : Callback<LoginResponse> {
            override fun onResponse(call: Call<LoginResponse>, response: Response<LoginResponse>) {
                if (response.isSuccessful ){
                        openSearchActivity()
                        saveTokenToPrefs(response.toString())
                    }else {

                }
            }

            override fun onFailure(call: Call<LoginResponse>, t: Throwable) {
            }
        })
    }

    val TOKENPREFSKEY = "tokenprefskey"
    private fun saveTokenToPrefs(token: String) {
        val pref = applicationContext.getSharedPreferences("CGEEnergy", 0)
        val editor = pref.edit()
        editor.putString(TOKENPREFSKEY, token)
        editor.commit()
    }

    private fun getTokenFromPrefs(): String? {
        val pref = applicationContext.getSharedPreferences("CGEEnergy", 0)
        return pref.getString(TOKENPREFSKEY, "")
    }

    private fun openSearchActivity() {
        val intent = Intent(this, SearchActivity::class.java)
        startActivity(intent)
        if (getTokenFromPrefs()?.length!! == 0) {
            openMainActivity()
        }
        finish()
    }
    private fun openMainActivity() {
        val intent = Intent(this, MainActivity::class.java)
        startActivity(intent)
        finish()
    }
}

My API.kt code: (EDITED AND CORRECTED by user Hello World )

interface Api {
    @POST("Login")
    @FormUrlEncoded
    fun login(@Field("username") username: String, @Field("password") password: String): Call<LoginResponse>
}

My LoginResponse.java code:

public class LoginResponse {

    @SerializedName("token")
    @Expose
    private String token;

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

}

Could someone help me with Basic Auth? Is there also a problem with my base URL? (added IP instead of localhost). Any tips would be very appreciated.

PS. for the http security issue, I have already added

android:usesCleartextTraffic="true"

in my AndroidManifest.xml

P Fuster :

Basic Auth requires an Authorization header in this format: "Basic " + Base64.encode(<username>:<password>)

You should change your Api interface like this

interface Api {
    @POST("Login")
    fun login(@Header("Authorization") authorization: String): Call<LoginResponse>
}

Now you can add an Auth header to the call like so:

val authPayload = "$userId:$password"
val data = authPayload.toByteArray()
val base64 = Base64.encodeToString(data, Base64.NO_WRAP)

val call = RequestManager.service.login("Basic $base64".trim())

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=7269&siteId=1