FINALLY SOLVED: NEEDED header("Content-Type", "application/json")
val (request, response, result) = Fuel.post(inputURL)
.header("Content-Type", "application/json")
.body(jsonElement.toString())
.response()
I was experiencing a 401 Unauthorized error when connecting my Android Studio AVD to my Rails 8 API, even though it worked with Postman. I followed the guidelines from https://husseinelgammal.hashnode.dev/implementing-an-authentication-in-a-ruby-on-rails-api-only-project-using-devise-and-jwt#heading-enabling-cors and updated config/devise.rb
with config.authentication_keys = [:name]
.
My MainActivity.kt
is as follows:
var baseURL = "http://10.0.2.2:3000/"
var connectURL = baseURL+"users/login"
var rrr: List<Any> = mutableListOf()
//MainClass body
fun connectButton(view: View) {
if (binding.loginNameField.text.isNotEmpty() && binding.loginPasswordField.text.isNotEmpty()) {
Thread{
rrr = fuelPost(connectURL)
}.start()
}
}
private fun fuelPost(inputURL: String,
name: String = binding.loginNameField.text.toString(),
password: String = binding.loginPasswordField.text.toString()): List<Any> {
val json = parseToJsonElement("""{"user":{"name":"$name","password":"$password"}}""")
val (request, response, result) = Fuel.post(inputURL).body(json.toString()).response()
Log.i("request", request.toString())
Log.i("response", response.toString())
Log.i("result", result.toString())
return listOf(request, response, result)
}
}
The Rails console logs show:
Started POST "/users/login" for 127.0.0.1 at 2025-01-15 15:18:05 +0200
Processing by Users::SessionsController#create as JSON
Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
The Android Studio console displays:
--> POST http://10.0.2.2:3000/users/login
Body : {"user":{"name":"MUSTDOS","password":"fakepass"}}
...
Body : {"error":"You need to sign in or sign up before continuing."}
.............
Here’s the relevant part of sessions_controller.rb
:
class Users::SessionsController < Devise::SessionsController
include RackSessionsFix
private
def respond_with(current_user, _opts = {})
logger.debug "current user: #{current_user.inspect}"
render "users/sessions/session_success", status: :ok
end
def respond_to_on_destroy
if current_user
render "users/sessions/session_destroy", status: :ok
else
render "users/sessions/session_destroy_errors", status: :unauthorized
end
end
end
And the CORS configuration in cors.rb
is:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins "*"
resource "*",
headers: :any,
expose: ["Authorization"],
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
In summary, the root issue was my Fuel POST request missing the required Content-Type: application/json
header. Adding it ensured Rails could parse the JSON payload correctly, resolving the 401 Unauthorized error.