I'm trying to do a login view with Volley Library.
It seems that "jsonobj" is always empty.
val jsonobj = JSONObject()
loginBtn.setOnClickListener {
jsonobj.put("mail", mailTxt.text)
jsonobj.put("pass", passTxt.text)
val que = Volley.newRequestQueue(this#MainActivity)
val req = JsonObjectRequest(Request.Method.POST, url, jsonobj,
Response.Listener{
response ->
toast(response["error"].toString())
}, Response.ErrorListener {
toast("Error")
})
que.add(req)
}
}
}
Related
I'm having the below Okhttp code:
val client = OkHttpClient()
val mediaType = MediaType.parse("application/x-www-form-urlencoded")
val body = RequestBody.create(mediaType, "tenant_id=xxxx&client_id=xxxx&client_secret=xxxx&resource=xxxx&grant_type=client_credentials")
val request = Request.Builder()
.url("https://sxxx.com/axxx/oauth2/token")
.post(body)
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.build()
val response = client.newCall(request).execute()
And want to convert it usint ktor, so I wrote the below:
class Greeting {
private val httpClient = HttpClient {
}
#Throws(Exception::class)
suspend fun greeting(): String {
val response = httpClient.request {
method = HttpMethod.Post
url {
protocol = URLProtocol.HTTPS
host = "sxxx.com"
path("axxx/oauth2/token")
// encodedParameters
trailingQuery = true
parameters.append("tenant_id", "xxxx")
parameters.append("client_id", "xxxx")
parameters.append("client_secret", "xxxx")
parameters.append("resource", "xxxx")
parameters.append("grant_type", "client_credentials")
}
headers {
append(HttpHeaders.ContentType, "application/x-www-form-urlencoded")
}
}
return response.bodyAsText()
}
}
And calling my new code as:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApplicationTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
val scope = rememberCoroutineScope()
var text by remember {
mutableStateOf("Loading")
}
LaunchedEffect(true){
scope.launch {
text = try {
Greeting().greeting()
} catch (e: Exception) {
e.localizedMessage ?: "error"
}
}
}
Greeting(text)
}
}
}
}
}
#Composable
fun Greeting(text: String) {
Text(text = text)
}
But instead of getting the required token, I'm getting the response: Chain validation failed
Make sure that:
Your server certificate is valid.
Your android system datetime is correct.
I got a problem with my Volley POST in kotlin :
When I use this following code, my application go on "Response.Listener", but the array is null, so when I try to display the information I've just send, I can only get "null".
May you guys help me? :)
There is the kotlin code :
private fun sendHtmlRequest(view: View){
val emailreq = view?.findViewById<EditText>(R.id.editText_email)
val pwdreq = view?.findViewById<EditText>(R.id.editText_password)
val email = emailreq.text.toString()
val pwd = pwdreq.text.toString()
val jsonobj = JSONObject()
var url = "https://www.dorian-roulet.com/testStage-master/mobileApp/testpostone.php"
jsonobj.put("mail", email)
jsonobj.put("pwd", pwd)
val que = Volley.newRequestQueue(context)
val req = JsonObjectRequest(Request.Method.POST, url, jsonobj,
Response.Listener { response ->
view.findViewById<TextView>(R.id.error_login)?.text = ("Ca marche $response $jsonobj")
println("Yessai")
}, Response.ErrorListener{
view.findViewById<TextView>(R.id.error_login)?.text = ("Ca marche pas mec $jsonobj")
println("Erreur")
}
)
que.add(req)
}
Now, there is the PHP code :
<?php
$reponse = array("mail" => $_POST["mail"], "pwd" => $_POST["pwd"]);
echo json_encode($reponse);
?>
I tried to use a GET to recieve this data from a GET array, but the problem still being...
And when I go on my server's logs, I cans ee that I have a POST request from my application (even if I can't see what's in the request).
I use this code to do a Login task, but atm, I just want to send a post request from my application.
Please help :)
EDIT: Your PHP code is NOT fine.
To get JSON data you should not use $_POST (even if it was send with post). Use this instead:
<?php
$data = json_decode(file_get_contents('php://input'), true);
$reponse = array("mail" => $data["mail"], "pwd" => $data["pwd"]);
echo json_encode($reponse);
?>
Here is a code that work for volley (it's not too different than what you have :-) ):
val jsonObjectRequest: JsonObjectRequest = object : JsonObjectRequest(Method.POST, url, **jsonobj**, Response.Listener { response: JSONObject ->
try {
val email = response.getString("email")
val password = response.getString("password")
} catch (e: JSONException) {
// catch/handle JSON error
} catch (e: Exception) {
// catch/handle other error
}
}, Response.ErrorListener { error: VolleyError ->
//Error Listener code
}) {
override fun getBodyContentType(): String {
return "application/x-www-form-urlencoded"
}
// you can override more functions here if needed (getHeader, etc.)
}
queue.add(jsonObjectRequest)
For your case it would likely give:
private fun sendHtmlRequest(view: View){
val emailreq = view?.findViewById<EditText>(R.id.editText_email)
val pwdreq = view?.findViewById<EditText>(R.id.editText_password)
val email = emailreq.text.toString()
val pwd = pwdreq.text.toString()
val jsonobj = JSONObject()
var url = "https://www.dorian-roulet.com/testStage-master/mobileApp/testpostone.php"
jsonobj.put("mail", email)
jsonobj.put("pwd", pwd)
val que = Volley.newRequestQueue(context)
val req = JsonObjectRequest(Request.Method.POST, url, jsonobj,
Response.Listener { response: JSONObject ->
val mailBack = response.getString("mail")
val pwdBack = response.getString("pwd")
view.findViewById<TextView>(R.id.error_login)?.text = ("Ca marche $response $mailBack - $pwdBack")
println("Yessai")
}, Response.ErrorListener{
view.findViewById<TextView>(R.id.error_login)?.text = ("Ca marche pas mec $jsonobj")
println("Erreur")
}
)
que.add(req)
}
There is the code I have after you send me what code I have to put inside :
(Still returns null values)
private fun sendHtmlRequest(view: View){
val emailreq = view?.findViewById<EditText>(R.id.editText_email)
val pwdreq = view?.findViewById<EditText>(R.id.editText_password)
val email = emailreq.text.toString()
val pwd = pwdreq.text.toString()
val jsonobj = JSONObject()
var url = "https://www.dorian-roulet.com/testStage-master/mobileApp/testpostone.php"
jsonobj.put("mail", email)
jsonobj.put("pwd", pwd)
val que = Volley.newRequestQueue(context)
val jsonObjectRequest = JsonObjectRequest(
Request.Method.POST, url, jsonobj,
Response.Listener { response: JSONObject ->
val emails = response.getString("mail")
val passwords = response.getString("pwd")
view.findViewById<TextView>(R.id.error_login)?.text = ("Ca marche $emails $passwords $response $jsonobj")
}, Response.ErrorListener {
view.findViewById<TextView>(R.id.error_login)?.text = ("Ca marche pas mec $jsonobj")
println("Erreur")
}) /*{
override fun getBodyContentType(): String {
return "application/x-www-form-urlencoded"
}
// you can override more functions here if needed (getHeader, etc.)
}*/
que.add(jsonObjectRequest)
}
I have the following code, where I validate the JWT token (with volley):
private fun validateToken(token: String) {
var queue = Volley.newRequestQueue(this)
val yourUrl = "https://mysite/wp-json/jwt-auth/v1/token/validate"
val parameters = JSONObject()
try {
parameters.put("username", "abc#test.com")
parameters.put("password", "12345678")
} catch (e: java.lang.Exception) {
}
val request: JsonObjectRequest =
object : JsonObjectRequest(
Method.POST, yourUrl, parameters,
Response.Listener { response -> Log.i("onResponse", response.toString()) },
Response.ErrorListener { error -> Log.e("onErrorResponse", error.toString()) }) {
#Throws(AuthFailureError::class)
override fun getHeaders(): Map<String, String> {
val headers: MutableMap<String, String> = HashMap()
// Basic Authentication
//String auth = "Basic " + Base64.encodeToString(CONSUMER_KEY_AND_SECRET.getBytes(), Base64.NO_WRAP);
headers["Authorization"] = "Bearer $token"
return headers
}
}
queue.add(request)
}
It works for me and I get the correct response from the server (in Log.i):
{"code":"jwt_auth_valid_token","data":{"status":200}}
My question is how in my code I do to be able to save the status: 200 in a variable so then it applies an ʻif status == 200` and if it is 200 then send it to another activity.
Add implementation 'com.google.code.gson:gson:2.8.6' to build.gradle(app)
Create Model.tk with:
data class dataServer (
#SerializedName("code") val code : String,
#SerializedName("data") val data : Data
)
data class Data (
#SerializedName("status") val status : Int
)
3. Update code:
private fun validateToken(token: String) {
var queue = Volley.newRequestQueue(this)
val yourUrl = "https://myweb/wp-json/jwt-auth/v1/token/validate"
val parameters = JSONObject()
try {
parameters.put("username", "abc#test.com")
parameters.put("password", "12345678")
} catch (e: java.lang.Exception) {
}
val request: JsonObjectRequest =
object : JsonObjectRequest(
Method.POST, yourUrl, parameters,
Response.Listener {
response ->
Log.i("onResponse", response.toString())
val gson = Gson()
val dataToken = gson.fromJson(response.toString(), dataServer::class.java)
val status = dataToken.data.status
println(status)
// use here if then
},
Response.ErrorListener { error -> Log.e("onErrorResponse", error.toString()) }) {
#Throws(AuthFailureError::class)
override fun getHeaders(): Map<String, String> {
val headers: MutableMap<String, String> = HashMap()
// Basic Authentication
//String auth = "Basic " + Base64.encodeToString(CONSUMER_KEY_AND_SECRET.getBytes(), Base64.NO_WRAP);
headers["Authorization"] = "Bearer $token"
return headers
}
}
queue.add(request)
}
I'm struggling to write tests for an endpoint that is under auth (token). In particular, when writing my test, I'm not able to chain the login request with my second request, despite providing the token received as part of the login request.
LoginEndpoint.kt
const val LOGIN_ENDPOINT = "$API_VERSION/login"
#Location(LOGIN_ENDPOINT)
class Login
fun Route.loginEndpoint(patientsRepository: Repository<Patient>, authProvider: AuthProvider) {
post<Login> {
val params = call.receive<Parameters>()
val userId = params["id"] ?: return#post call.respond(status = HttpStatusCode.BadRequest, message = "Missing user id")
val user = patientsRepository.get(userId)
if (user != null) {
val token = authProvider.generateToken(user.id!!)
call.respond(TextContent("{ \"token\": \"$token\" }", ContentType.Application.Json))
} else {
call.respond(status = HttpStatusCode.NotFound, message = "User with id $userId does not exist")
}
}
}
LoginEndpointTest.kt (passing, all good)
#Test
fun `given user exists then returns 200 and token`() {
val userId = "paco123"
val token = "magic_token_123"
withTestApplication({
givenTestModule()
}) {
every { authProvider.generateToken(userId) } answers { token }
givenPatientExists(userId)
with(handleRequest(HttpMethod.Post, "/$API_VERSION/login") {
addHeader("content-type", "application/x-www-form-urlencoded")
setBody("id=$userId")
}) {
assertEquals(HttpStatusCode.OK, response.status())
assertEquals("{ \"token\": \"magic_token_123\" }", response.content)
}
}
}
private fun Application.givenTestModule() {
module(
testing = true,
repositoryModule = TestingRepositoryModule,
authProvider = authProvider
)
}
Now, the problematic endpoint.
ProfileEndpoint.kt
const val PATIENTS_API_ENDPOINT = "$API_VERSION/profile"
#Location(PATIENTS_API_ENDPOINT)
class ProfileEndpoint
fun Route.profileEndpoint(patientsRepository: Repository<Patient>) {
authenticate("jwt") {
get<ProfileEndpoint> {
val apiUser: Patient = call.apiUser!!
val id = apiUser.id!!
val patient = patientsRepository.get(id)
when (patient != null) {
false -> call.respond(status = HttpStatusCode.NotFound, message = "Patient with id $id does not exist")
true -> call.respond(status = HttpStatusCode.OK, message = patient.map())
}
}
}
}
Finally, my failing test
ProfileEndpointTest.kt
#Test
fun `given user is logged in then returns 200 and profile`() {
val userId = "paco123"
val token = "magic_token_123"
withTestApplication({
givenTestModule()
}) {
every { authProvider.generateToken(userId) } answers { token }
givenPatientExists(userId)
handleRequest(HttpMethod.Post, "/$API_VERSION/login") {
addHeader("content-type", "application/x-www-form-urlencoded")
setBody("id=$userId")
}
handleRequest(HttpMethod.Get, "/$API_VERSION/profile") {
addHeader("Authorization", "Bearer $token")
}.apply {
assertEquals(HttpStatusCode.OK, response.status())
}
}
}
The error is:
expected:<200 OK> but was:<401 Unauthorized>
Expected :200 OK
Actual :401 Unauthorized
AuthProvider.kt
open class AuthProvider(secret: String = System.getenv(Environment.JWT_SECRET)) {
private val algorithm = Algorithm.HMAC512(secret)
fun getVerifier(): JWTVerifier = JWT
.require(algorithm)
.withIssuer(APP_NAME)
.build()
fun generateToken(userId: String): String = JWT.create()
.withSubject(SUBJECT)
.withIssuer(APP_NAME)
.withClaim(CLAIM, userId)
.withExpiresAt(expiresAt())
.sign(algorithm)
private fun expiresAt() = Date(System.currentTimeMillis() + MILLIES_PER_DAY * TOKEN_DAYS_LENGTH)
}
val ApplicationCall.apiUser get() = authentication.principal<Patient>()
I've tried using cookiesSession like in this documentation's example https://ktor.io/servers/testing.html#preserving-cookies but it didn't work. Any help would be much appreciated.
I've a php file on a server, and I have to fetch the information but i don't know how to pass a parameter to the query.
For example, if I have this query: SELECT * FROM accounttable WHERE idaccount = 1, i want to pass this 1 as a parameter, how can i do?
val stringRequest = StringRequest(Request.Method.POST, URL, Response.Listener<String>{ s ->
try {
val array = JSONArray(s)
for (i in 0..array.length() - 1) {
val objectAccount = array.getJSONObject(i)
val account = Account(
objectAccount.getString("accountplace"),
objectAccount.getString("useraccount"),
objectAccount.getString("accountpass"))
listAccounts.add(account)
}
}catch (e: JSONException){
e.printStackTrace()
}
}, Response.ErrorListener { error: VolleyError? -> Log.e("error", "error") })
val requesQueue = Volley.newRequestQueue(this)
requesQueue.add<String>(stringRequest)
You need to override the getParams() method on your Request. In order to do that you can either subclass StringRequest, or create an object expression (similar to an anonymous inner class from Java); as shown below.
val stringRequest = object : StringRequest(Request.Method.POST, URL, Response.Listener { s ->
// Your success code here
}, Response.ErrorListener { e ->
// Your error code here
}) {
override fun getParams(): Map<String, String> = mapOf("idaccount" to "1")
}