Skip to content

Commit 3bf591b

Browse files
committed
Added URI validation for subject_token_type in CTE
1 parent 0ea3a10 commit 3bf591b

8 files changed

Lines changed: 139 additions & 5 deletions

File tree

auth0/src/main/java/com/auth0/android/authentication/AuthenticationAPIClient.kt

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,23 @@ import com.auth0.android.NetworkErrorException
88
import com.auth0.android.dpop.DPoP
99
import com.auth0.android.dpop.DPoPException
1010
import com.auth0.android.dpop.SenderConstraining
11-
import com.auth0.android.request.*
12-
import com.auth0.android.request.internal.*
11+
import com.auth0.android.request.AuthenticationRequest
12+
import com.auth0.android.request.ErrorAdapter
13+
import com.auth0.android.request.JsonAdapter
14+
import com.auth0.android.request.ProfileRequest
15+
import com.auth0.android.request.PublicKeyCredentials
16+
import com.auth0.android.request.Request
17+
import com.auth0.android.request.SignUpRequest
18+
import com.auth0.android.request.UserData
19+
import com.auth0.android.request.internal.BaseAuthenticationRequest
20+
import com.auth0.android.request.internal.BaseRequest
21+
import com.auth0.android.request.internal.GsonAdapter
1322
import com.auth0.android.request.internal.GsonAdapter.Companion.forMap
1423
import com.auth0.android.request.internal.GsonAdapter.Companion.forMapOf
24+
import com.auth0.android.request.internal.GsonProvider
25+
import com.auth0.android.request.internal.RequestFactory
1526
import com.auth0.android.request.internal.ResponseUtils.isNetworkError
27+
import com.auth0.android.request.internal.validator.CustomTokenExchangeValidator
1628
import com.auth0.android.result.Challenge
1729
import com.auth0.android.result.Credentials
1830
import com.auth0.android.result.DatabaseUser
@@ -758,6 +770,7 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
758770
organization: String? = null
759771
): AuthenticationRequest {
760772
return tokenExchange(subjectTokenType, subjectToken, organization)
773+
.addValidator(CustomTokenExchangeValidator())
761774
}
762775

763776
/**

auth0/src/main/java/com/auth0/android/request/AuthenticationRequest.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.auth0.android.request
22

33
import com.auth0.android.Auth0
44
import com.auth0.android.authentication.AuthenticationException
5-
import com.auth0.android.callback.Callback
65
import com.auth0.android.result.Credentials
76

87
/**
@@ -74,4 +73,15 @@ public interface AuthenticationRequest : Request<Credentials, AuthenticationExce
7473
* @return the current builder instance
7574
*/
7675
public fun withIdTokenVerificationIssuer(issuer: String): AuthenticationRequest
76+
77+
/**
78+
* Adds a validator to be executed before the request is sent.
79+
* Multiple validators can be added and will be executed in order.
80+
*
81+
* @param validator the validator to add
82+
* @return itself
83+
*/
84+
override fun addValidator(validator: RequestValidator): AuthenticationRequest {
85+
return this
86+
}
7787
}

auth0/src/main/java/com/auth0/android/request/Request.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,15 @@ public interface Request<T, U : Auth0Exception> {
7676
* @return itself
7777
*/
7878
public fun addHeader(name: String, value: String): Request<T, U>
79+
80+
/**
81+
* Adds a validator to be executed before the request is sent.
82+
* Multiple validators can be added and will be executed in order.
83+
*
84+
* @param validator the validator to add
85+
* @return itself
86+
*/
87+
public fun addValidator(validator: RequestValidator): Request<T, U> {
88+
return this
89+
}
7990
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.auth0.android.request
2+
3+
import com.auth0.android.Auth0Exception
4+
5+
/**
6+
* Interface for validating request parameters before execution.
7+
* Validators are invoked before the network request is made.
8+
*/
9+
public interface RequestValidator {
10+
11+
/**
12+
* Validates the request options and parameters.
13+
* @param options the request options to validate
14+
* @throws Auth0Exception if validation fails
15+
*/
16+
@Throws(Auth0Exception::class)
17+
public fun validate(options: RequestOptions)
18+
}

auth0/src/main/java/com/auth0/android/request/SignUpRequest.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ public class SignUpRequest
9191
return this
9292
}
9393

94+
override fun addValidator(validator: RequestValidator): AuthenticationRequest {
95+
authenticationRequest.addValidator(validator)
96+
return this
97+
}
98+
9499
override fun withIdTokenVerificationLeeway(leeway: Int): SignUpRequest {
95100
authenticationRequest.withIdTokenVerificationLeeway(leeway)
96101
return this

auth0/src/main/java/com/auth0/android/request/internal/BaseAuthenticationRequest.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,16 @@ import com.auth0.android.Auth0Exception
77
import com.auth0.android.authentication.AuthenticationException
88
import com.auth0.android.authentication.ParameterBuilder
99
import com.auth0.android.callback.Callback
10-
import com.auth0.android.provider.*
10+
import com.auth0.android.provider.IdTokenMissingException
11+
import com.auth0.android.provider.IdTokenVerificationOptions
12+
import com.auth0.android.provider.IdTokenVerifier
13+
import com.auth0.android.provider.TokenValidationException
14+
import com.auth0.android.provider.UnexpectedIdTokenException
1115
import com.auth0.android.request.AuthenticationRequest
1216
import com.auth0.android.request.Request
17+
import com.auth0.android.request.RequestValidator
1318
import com.auth0.android.result.Credentials
14-
import java.util.*
19+
import java.util.Date
1520

1621
internal open class BaseAuthenticationRequest(
1722
private val request: Request<Credentials, AuthenticationException>,
@@ -97,6 +102,11 @@ internal open class BaseAuthenticationRequest(
97102
return this
98103
}
99104

105+
override fun addValidator(validator: RequestValidator): AuthenticationRequest {
106+
request.addValidator(validator)
107+
return this
108+
}
109+
100110
override fun validateClaims(): AuthenticationRequest {
101111
this.validateClaims = true
102112
return this

auth0/src/main/java/com/auth0/android/request/internal/BaseRequest.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.auth0.android.request.JsonAdapter
1212
import com.auth0.android.request.NetworkingClient
1313
import com.auth0.android.request.Request
1414
import com.auth0.android.request.RequestOptions
15+
import com.auth0.android.request.RequestValidator
1516
import com.auth0.android.request.ServerResponse
1617
import kotlinx.coroutines.CoroutineDispatcher
1718
import kotlinx.coroutines.Dispatchers
@@ -40,6 +41,8 @@ internal open class BaseRequest<T, U : Auth0Exception>(
4041

4142
private val options: RequestOptions = RequestOptions(method)
4243

44+
private val validators = mutableListOf<RequestValidator>()
45+
4346
override fun addHeader(name: String, value: String): Request<T, U> {
4447
options.headers[name] = value
4548
return this
@@ -70,6 +73,11 @@ internal open class BaseRequest<T, U : Auth0Exception>(
7073
return this
7174
}
7275

76+
override fun addValidator(validator: RequestValidator): Request<T, U> {
77+
validators.add(validator)
78+
return this
79+
}
80+
7381
/**
7482
* Runs asynchronously and executes the network request, without blocking the current thread.
7583
* The result is parsed into a <T> value and posted in the callback's onSuccess method or a <U>
@@ -126,6 +134,7 @@ internal open class BaseRequest<T, U : Auth0Exception>(
126134
*/
127135
@kotlin.jvm.Throws(Auth0Exception::class)
128136
override fun execute(): T {
137+
runClientValidation()
129138
val response: ServerResponse
130139
try {
131140
if (dPoP?.shouldGenerateProof(url, options.parameters) == true) {
@@ -176,4 +185,10 @@ internal open class BaseRequest<T, U : Auth0Exception>(
176185
}
177186
}
178187

188+
private fun runClientValidation() {
189+
validators.forEach { validator ->
190+
validator.validate(options)
191+
}
192+
}
193+
179194
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.auth0.android.request.internal.validator
2+
3+
import com.auth0.android.authentication.AuthenticationException
4+
import com.auth0.android.request.RequestOptions
5+
import com.auth0.android.request.RequestValidator
6+
import java.net.URI
7+
8+
/**
9+
* Client side validation for custom token exchange
10+
*/
11+
public class CustomTokenExchangeValidator : RequestValidator {
12+
13+
private val reservedNameSpace = listOf(
14+
"http://auth0.com",
15+
"https://auth0.com",
16+
"http://okta.com",
17+
"https://okta.com",
18+
"urn:ietf",
19+
"urn:auth0",
20+
"urn:okta"
21+
)
22+
23+
override fun validate(options: RequestOptions) {
24+
val subjectTokenType = options.parameters["subject_token_type"] as String
25+
26+
// Check if it's a reserved namespace
27+
if (reservedNameSpace.contains(subjectTokenType)) {
28+
throw AuthenticationException(
29+
"Invalid URI", IllegalArgumentException(
30+
"The passed URI is a reserved namespace and cannot be used"
31+
)
32+
)
33+
}
34+
35+
// If it starts with http:// or https://, validate it as a URI
36+
if (subjectTokenType.startsWith(
37+
"http://",
38+
ignoreCase = true
39+
) || subjectTokenType.startsWith("https://", ignoreCase = true)
40+
) {
41+
runCatching {
42+
URI(subjectTokenType)
43+
}.onFailure { error ->
44+
throw AuthenticationException(
45+
"Invalid URI", IllegalArgumentException(
46+
"The subject_token_type is not a valid URI: ${error.message}"
47+
)
48+
)
49+
}
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)