Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ private String refreshToken(

String clientIdForRequest = null;
String clientSecretForRequest = null;
String clientAuth = null;

if (clientId == null) {
Timber.d("Client Id not stored. Let's use the hardcoded one");
Expand All @@ -362,20 +363,29 @@ private String refreshToken(
// Use token endpoint retrieved from oidc discovery
tokenEndpoint = oidcServerConfigurationUseCaseResult.getDataOrNull().getTokenEndpoint();

// RFC 7636: Public clients (token_endpoint_auth_method: none) must not send Authorization header
if (oidcServerConfigurationUseCaseResult.getDataOrNull() != null &&
oidcServerConfigurationUseCaseResult.getDataOrNull().isTokenEndpointAuthMethodSupportedClientSecretPost()) {
oidcServerConfigurationUseCaseResult.getDataOrNull().isTokenEndpointAuthMethodNone()) {
clientAuth = null;
clientIdForRequest = clientId;
} else if (oidcServerConfigurationUseCaseResult.getDataOrNull() != null &&
oidcServerConfigurationUseCaseResult.getDataOrNull().isTokenEndpointAuthMethodSupportedClientSecretPost()) {
// For client_secret_post, credentials go in body, not Authorization header
clientAuth = null;
clientIdForRequest = clientId;
clientSecretForRequest = clientSecret;
} else {
// For other methods (e.g., client_secret_basic), use Basic auth header
clientAuth = OAuthUtils.Companion.getClientAuth(clientSecret, clientId);
}
} else {
Timber.d("OIDC Discovery failed. Server discovery info: [ %s ]",
oidcServerConfigurationUseCaseResult.getThrowableOrNull().toString());

tokenEndpoint = baseUrl + File.separator + mContext.getString(R.string.oauth2_url_endpoint_access);
clientAuth = OAuthUtils.Companion.getClientAuth(clientSecret, clientId);
}

String clientAuth = OAuthUtils.Companion.getClientAuth(clientSecret, clientId);

String scope = mContext.getResources().getString(R.string.oauth2_openid_scope);

TokenRequest oauthTokenRequest = new TokenRequest.RefreshToken(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -604,28 +604,41 @@ class LoginActivity : AppCompatActivity(), SslUntrustedCertDialog.OnSslUntrusted

val clientRegistrationInfo = authenticationViewModel.registerClient.value?.peekContent()?.getStoredData()

val clientAuth = if (clientRegistrationInfo?.clientId != null && clientRegistrationInfo.clientSecret != null) {
OAuthUtils.getClientAuth(clientRegistrationInfo.clientSecret as String, clientRegistrationInfo.clientId)

} else {
OAuthUtils.getClientAuth(getString(R.string.oauth2_client_secret), getString(R.string.oauth2_client_id))
}

// Use oidc discovery one, or build an oauth endpoint using serverBaseUrl + Setup string.
val tokenEndPoint: String

var clientId: String? = null
var clientSecret: String? = null
var clientAuth: String? = null

val serverInfo = authenticationViewModel.serverInfo.value?.peekContent()?.getStoredData()
if (serverInfo is ServerInfo.OIDCServer) {
tokenEndPoint = serverInfo.oidcServerConfiguration.tokenEndpoint
if (serverInfo.oidcServerConfiguration.isTokenEndpointAuthMethodSupportedClientSecretPost()) {

// RFC 7636: Public clients (token_endpoint_auth_method: none) must not send Authorization header
if (serverInfo.oidcServerConfiguration.isTokenEndpointAuthMethodNone()) {
clientAuth = null
clientId = clientRegistrationInfo?.clientId ?: contextProvider.getString(R.string.oauth2_client_id)
} else if (serverInfo.oidcServerConfiguration.isTokenEndpointAuthMethodSupportedClientSecretPost()) {
// For client_secret_post, credentials go in body, not Authorization header
clientAuth = null
clientId = clientRegistrationInfo?.clientId ?: contextProvider.getString(R.string.oauth2_client_id)
clientSecret = clientRegistrationInfo?.clientSecret ?: contextProvider.getString(R.string.oauth2_client_secret)
} else {
// For other methods (e.g., client_secret_basic), use Basic auth header
clientAuth = if (clientRegistrationInfo?.clientId != null && clientRegistrationInfo.clientSecret != null) {
OAuthUtils.getClientAuth(clientRegistrationInfo.clientSecret as String, clientRegistrationInfo.clientId)
} else {
OAuthUtils.getClientAuth(getString(R.string.oauth2_client_secret), getString(R.string.oauth2_client_id))
}
}
} else {
tokenEndPoint = "$serverBaseUrl${File.separator}${contextProvider.getString(R.string.oauth2_url_endpoint_access)}"
clientAuth = if (clientRegistrationInfo?.clientId != null && clientRegistrationInfo.clientSecret != null) {
OAuthUtils.getClientAuth(clientRegistrationInfo.clientSecret as String, clientRegistrationInfo.clientId)
} else {
OAuthUtils.getClientAuth(getString(R.string.oauth2_client_secret), getString(R.string.oauth2_client_id))
}
}

val scope = resources.getString(R.string.oauth2_openid_scope)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ class TokenRequestRemoteOperation(

val postMethod = PostMethod(URL(tokenRequestParams.tokenEndpoint), requestBody)

postMethod.addRequestHeader(AUTHORIZATION_HEADER, tokenRequestParams.clientAuth)
tokenRequestParams.clientAuth?.takeIf { it.isNotEmpty() }?.let {
postMethod.addRequestHeader(AUTHORIZATION_HEADER, it)
}

val status = client.executeHttpMethod(postMethod)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import okhttp3.RequestBody

sealed class TokenRequestParams(
val tokenEndpoint: String,
val clientAuth: String,
val clientAuth: String?,
val grantType: String,
val scope: String,
val clientId: String?,
Expand All @@ -40,7 +40,7 @@ sealed class TokenRequestParams(

class Authorization(
tokenEndpoint: String,
clientAuth: String,
clientAuth: String?,
grantType: String,
scope: String,
clientId: String?,
Expand All @@ -65,7 +65,7 @@ sealed class TokenRequestParams(

class RefreshToken(
tokenEndpoint: String,
clientAuth: String,
clientAuth: String?,
grantType: String,
scope: String,
clientId: String?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@ data class OIDCServerConfiguration(
) {
fun isTokenEndpointAuthMethodSupportedClientSecretPost(): Boolean =
tokenEndpointAuthMethodsSupported?.any { it == "client_secret_post" } ?: false

fun isTokenEndpointAuthMethodNone(): Boolean =
tokenEndpointAuthMethodsSupported?.any { it == "none" } ?: false
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ package eu.opencloud.android.domain.authentication.oauth.model
sealed class TokenRequest(
val baseUrl: String,
val tokenEndpoint: String,
val clientAuth: String,
val clientAuth: String?,
val grantType: String,
val scope: String,
val clientId: String?,
Expand All @@ -33,7 +33,7 @@ sealed class TokenRequest(
class AccessToken(
baseUrl: String,
tokenEndpoint: String,
clientAuth: String,
clientAuth: String?,
scope: String,
clientId: String? = null,
clientSecret: String? = null,
Expand All @@ -45,7 +45,7 @@ sealed class TokenRequest(
class RefreshToken(
baseUrl: String,
tokenEndpoint: String,
clientAuth: String,
clientAuth: String?,
scope: String,
clientId: String? = null,
clientSecret: String? = null,
Expand Down