Closed johnnyzen closed 2 years ago
Thanks for posting! I'll forward this to our Android SDK team for addressal.
Hi @johnnyzen Could you please give us a code snippet of what's triggering this error?
Another area you could help is by seeing if the request is getting to Okta by checking the system log. You will have to change the URL, but it should be something along the lines of https://dev-change_me-admin.okta.com/report/system_log_2 for your org.
Update: After going through hell, it appears Android Studio + Profiling is causing this issue.
I wasnt even using profiling, so maybe Android Studio is also doing some kind of profiling without user action in some situations.
Somehow it seems Android Studio is interfering with the request, but cannot find out what it is doing exactly.
Android Studio 4.2.1
Steps to reproduce.
1) Run application 2) Turn on profiling 3) Try to login using okta 4) Fails to login until I close profiling and relaunch app. - then it works.
I guess this is something I will investigate further with Android Studio, so I think this can be closed.
Although would be interesting if anyone can reproduce.
Hope this helps anyone experiencing the same issue.
Thanks for the update! I know part of Android Studio profiling includes intercepting/logging okhttp requests. If you want to use it, you might need to update the version of OkHttp you're using.
I'll close this for now, but feel free to reopen, or open a new issue if you run into problems.
I know you guys are quite strict with the json.
This is the request I can see in the profiler when its failing. Maybe Android Studio is adding null to the relay state? Could this cause the request to fail on your side?
{
"relayState": null,
"password": "xxxxxx",
"username": "xxxxxx"
}
Raised with Android Studio bug tracker: https://issuetracker.google.com/issues/195441726
Could you give me a code snippet of how you're triggering the authentication?
My guess is that you're using https://github.com/okta/okta-auth-java not okta-oidc-android. (I'm happy to help you here either way, but it'll just make it easier for me to help you!)
fun oktaNetworkLogin(loginRequest: OktaLoginRequest): LiveData<Resource<AuthenticationResponse>> {
val response: MutableLiveData<Resource<AuthenticationResponse>> = MutableLiveData()
appExecutors.diskIO().execute {
val client = AuthenticationClients.builder()
.setOrgUrl("https://apps.****.com")
.build()
try {
client.authenticate(
loginRequest.username,
loginRequest.password.toCharArray(),
null,
object : AuthenticationStateHandlerAdapter() {
override fun handleUnknown(authenticationResponse: AuthenticationResponse) {
Timber.d("handleUnknown ${authenticationResponse.status.name}")
response.postValue(
Resource(
Status.ERROR,
authenticationResponse,
"Server error. Please contact IT support."
)
)
}
override fun handleLockedOut(lockedOut: AuthenticationResponse) {
Timber.d("handleLockedOut ${lockedOut.status.name}")
response.postValue(
Resource(
Status.ERROR,
lockedOut,
"You are locked out from your account. Please contact IT support."
)
)
}
override fun handleSuccess(successResponse: AuthenticationResponse) {
val sessionToken = successResponse.sessionToken
Timber.d("successResponse: Session Token: $sessionToken")
response.postValue(Resource(Status.SUCCESS, successResponse, null))
}
})
} catch (e: Exception) {
Timber.e("AuthenticationException $e")
response.postValue(
Resource(
Status.ERROR,
null,
"Authentication failed. Please check details and try again.",
ErrorResponse(0)
)
)
}
}
return response
}
implementation 'com.okta.android:oidc-androidx:1.0.16'
implementation 'com.okta.jwt:okta-jwt-verifier-impl:0.5.0'
implementation 'com.okta.authn.sdk:okta-authn-sdk-api:1.0.0'
implementation('com.okta.authn.sdk:okta-authn-sdk-impl:1.0.0') {
exclude group: 'com.okta.sdk', module: 'okta-sdk-httpclient'
}
implementation 'com.okta.sdk:okta-sdk-okhttp:1.5.2'
In our custom sign in example, https://github.com/okta/samples-android/tree/master/custom-sign-in
We're using:
implementation 'com.okta.authn.sdk:okta-authn-sdk-api:2.0.0'
runtimeOnly 'com.okta.authn.sdk:okta-authn-sdk-impl:2.0.0'
runtimeOnly 'com.okta.sdk:okta-sdk-okhttp:2.0.0'
runtimeOnly 'com.squareup.okhttp3:okhttp:4.9.0'
My guess is if you pull in the latest okta-sdk-okhttp and a newer okhttp, it'll work!
Thanks @JayNewstrom I have applied the latest and greatest but still getting the same error.
I am pretty sure the problem lies with something Android Studio is doing. Maybe reconstructing the request and invalidating what you guys require.
Ok, if you can reproduce in one of our samples, I'd be happy to take a look.
Sure I will give it a go :) thanks for your time and assistance @JayNewstrom
@JayNewstrom Managed to recreate using your sample code. cloned your custom sign in code.
Changes I made to the sample project was literally okta_oidc_config details and changed base url.
So, I was able to recreate this, and it looks like when using the Android Studio profiler, it's not passing request data along to the server. I was able to see this by introspecting the traffic using Charles Proxy.
I'm guessing this is an issue with either Android studio or deep in our okta commons SDK. For now, I'd recommend turning off the profiler.
Nice one @JayNewstrom for recreating. Will disable for now, and hopefully anyone else experiencing the same issue doesnt have to swear and curse the amount of times working out whats wrong.
Hi @JayNewstrom
Google has responded, but its a bit over my head.
Can you understand this better than I can do?
Hello. Thanks for reporting this issue. It looks like the issue is on the outgoing request? Our interceptor doesn't modify any of the request headers and body, only reads.
With that being said, we have had issues before where upstream interceptors supply a body that can't be read more than once. And our profiling tool calls writeTo so it can peek at the request body, effectively "using up" the body. By the time the request gets sent out, its body is in a bad state.
I'm not familiar with Okta, but could that be a plausible explanation?
Sounds like those assumptions are correct. And the body is implemented as an input stream. Which is why it can't be read twice:
I don't think we want to "fix" this in our commons sdk, since what we're doing is the most efficient. But if you want it to work in your app, you could add an OkHttp Interceptor that wraps the request body with a Buffer.
Thanks @JayNewstrom I will look into the interceptor, I think I use anyways, but will be interesting to see if I can find a solution.
Best wishes
Hi all, started getting this error when logging in, without any changes to my code.
Okta E0000003 (The request body was not well-formed.)
//Okta implementation 'com.okta.android:oidc-androidx:1.0.16' implementation 'com.okta.jwt:okta-jwt-verifier-impl:0.5.0' implementation 'com.okta.authn.sdk:okta-authn-sdk-api:1.0.0' implementation('com.okta.authn.sdk:okta-authn-sdk-impl:1.0.0') { exclude group: 'com.okta.sdk', module: 'okta-sdk-httpclient' } implementation 'com.okta.sdk:okta-sdk-okhttp:1.5.2'
Android 11 - Samsung s10
Any ideas on why this is happening, or any logs I can look at?