Skip to content

Commit 5010ce0

Browse files
committed
Enable overriding logoutUrl and authorizeUrl
1 parent f78ef0e commit 5010ce0

File tree

9 files changed

+231
-62
lines changed

9 files changed

+231
-62
lines changed

auth0/src/main/java/com/auth0/android/Auth0.kt

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -72,48 +72,22 @@ public open class Auth0 private constructor(
7272
* @return Url to call to perform the web flow of OAuth
7373
*/
7474
public open val authorizeUrl: String
75-
get() = buildAuthorizeUrl()
76-
77-
/**
78-
* Builds the authorize URL for the current domain.
79-
*
80-
* This function constructs the URL used for the OAuth 2.0 authorization flow. Subclasses
81-
* can override this function to modify the URL generation logic, for example, to use a
82-
* different endpoint or add custom query parameters.
83-
*
84-
* @return The URL to call to perform the web flow of OAuth.
85-
*/
86-
public open fun buildAuthorizeUrl(): String { // Function instead of property
87-
return domainUrl.newBuilder()
75+
get() = domainUrl.newBuilder()
8876
.addEncodedPathSegment("authorize")
8977
.build()
9078
.toString()
91-
}
9279

9380
/**
9481
* Obtain the logout URL for the current domain
9582
*
9683
* @return Url to call to perform the web logout
9784
*/
9885
public open val logoutUrl: String
99-
get() = buildLogoutUrl()
100-
101-
/**
102-
* Builds the logout URL for the current domain.
103-
*
104-
* This function constructs the URL used for the logout process. Subclasses can override
105-
* this function to modify the URL generation logic, for example, to use a different
106-
* endpoint or add custom query parameters.
107-
*
108-
* @return The URL to call to perform the web logout.
109-
*/
110-
public open fun buildLogoutUrl(): String { // Function instead of property
111-
return domainUrl.newBuilder()
86+
get() = domainUrl.newBuilder()
11287
.addEncodedPathSegment("v2")
11388
.addEncodedPathSegment("logout")
11489
.build()
11590
.toString()
116-
}
11791

11892

11993
public companion object {
@@ -188,4 +162,4 @@ public open class Auth0 private constructor(
188162
return safeUrl.toHttpUrlOrNull()
189163
}
190164
}
191-
}
165+
}

auth0/src/main/java/com/auth0/android/provider/LogoutManager.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ internal class LogoutManager(
1515
ctOptions: CustomTabsOptions,
1616
federated: Boolean = false,
1717
private val launchAsTwa: Boolean = false,
18+
private val customLogoutUrl: String? = null
1819
) : ResumableManager() {
1920
private val parameters: MutableMap<String, String>
2021
private val ctOptions: CustomTabsOptions
@@ -42,7 +43,8 @@ internal class LogoutManager(
4243
}
4344

4445
private fun buildLogoutUri(): Uri {
45-
val logoutUri = Uri.parse(account.logoutUrl)
46+
val urlToUse = customLogoutUrl ?: account.logoutUrl
47+
val logoutUri = Uri.parse(urlToUse)
4648
val builder = logoutUri.buildUpon()
4749
for ((key, value) in parameters) {
4850
builder.appendQueryParameter(key, value)

auth0/src/main/java/com/auth0/android/provider/OAuthManager.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ internal class OAuthManager(
2525
parameters: Map<String, String>,
2626
ctOptions: CustomTabsOptions,
2727
private val launchAsTwa: Boolean = false,
28+
private val customAuthorizeUrl: String? = null
2829
) : ResumableManager() {
2930
private val parameters: MutableMap<String, String>
3031
private val headers: MutableMap<String, String>
@@ -197,6 +198,7 @@ internal class OAuthManager(
197198
auth0 = account,
198199
idTokenVerificationIssuer = idTokenVerificationIssuer,
199200
idTokenVerificationLeeway = idTokenVerificationLeeway,
201+
customAuthorizeUrl = this.customAuthorizeUrl
200202
)
201203
}
202204

@@ -235,7 +237,8 @@ internal class OAuthManager(
235237
}
236238

237239
private fun buildAuthorizeUri(): Uri {
238-
val authorizeUri = Uri.parse(account.authorizeUrl)
240+
val urlToUse = customAuthorizeUrl ?: account.authorizeUrl
241+
val authorizeUri = Uri.parse(urlToUse)
239242
val builder = authorizeUri.buildUpon()
240243
for ((key, value) in parameters) {
241244
builder.appendQueryParameter(key, value)
@@ -357,7 +360,8 @@ internal fun OAuthManager.Companion.fromState(
357360
account = state.auth0,
358361
ctOptions = state.ctOptions,
359362
parameters = state.parameters,
360-
callback = callback
363+
callback = callback,
364+
customAuthorizeUrl = state.customAuthorizeUrl
361365
).apply {
362366
setHeaders(
363367
state.headers

auth0/src/main/java/com/auth0/android/provider/OAuthManagerState.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ internal data class OAuthManagerState(
1717
val ctOptions: CustomTabsOptions,
1818
val pkce: PKCE?,
1919
val idTokenVerificationLeeway: Int?,
20-
val idTokenVerificationIssuer: String?
20+
val idTokenVerificationIssuer: String?,
21+
val customAuthorizeUrl: String? = null
2122
) {
2223

2324
private class OAuthManagerJson(
@@ -32,7 +33,8 @@ internal data class OAuthManagerState(
3233
val codeChallenge: String,
3334
val codeVerifier: String,
3435
val idTokenVerificationLeeway: Int?,
35-
val idTokenVerificationIssuer: String?
36+
val idTokenVerificationIssuer: String?,
37+
val customAuthorizeUrl: String? = null
3638
)
3739

3840
fun serializeToJson(
@@ -56,6 +58,7 @@ internal data class OAuthManagerState(
5658
codeChallenge = pkce?.codeChallenge.orEmpty(),
5759
idTokenVerificationIssuer = idTokenVerificationIssuer,
5860
idTokenVerificationLeeway = idTokenVerificationLeeway,
61+
customAuthorizeUrl = this.customAuthorizeUrl
5962
)
6063
return gson.toJson(json)
6164
} finally {
@@ -103,6 +106,7 @@ internal data class OAuthManagerState(
103106
),
104107
idTokenVerificationIssuer = oauthManagerJson.idTokenVerificationIssuer,
105108
idTokenVerificationLeeway = oauthManagerJson.idTokenVerificationLeeway,
109+
customAuthorizeUrl = oauthManagerJson.customAuthorizeUrl
106110
)
107111
} finally {
108112
parcel.recycle()

auth0/src/main/java/com/auth0/android/provider/WebAuthProvider.kt

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ public object WebAuthProvider {
148148
private var ctOptions: CustomTabsOptions = CustomTabsOptions.newBuilder().build()
149149
private var federated: Boolean = false
150150
private var launchAsTwa: Boolean = false
151+
private var customLogoutUrl: String? = null
151152

152153
/**
153154
* When using a Custom Tabs compatible Browser, apply these customization options.
@@ -215,6 +216,18 @@ public object WebAuthProvider {
215216
return this
216217
}
217218

219+
/**
220+
* Specifies a custom Logout URL to use for this logout request, overriding the default
221+
* generated from the Auth0 domain (account.logoutUrl).
222+
*
223+
* @param logoutUrl the custom logout URL.
224+
* @return the current builder instance
225+
*/
226+
public fun withLogoutUrl(logoutUrl: String): LogoutBuilder {
227+
this.customLogoutUrl = logoutUrl
228+
return this
229+
}
230+
218231
/**
219232
* Request the user session to be cleared. When successful, the callback will get invoked.
220233
* An error is raised if there are no browser applications installed in the device or if
@@ -248,7 +261,8 @@ public object WebAuthProvider {
248261
returnToUrl!!,
249262
ctOptions,
250263
federated,
251-
launchAsTwa
264+
launchAsTwa,
265+
customLogoutUrl
252266
)
253267
managerInstance = logoutManager
254268
logoutManager.startLogout(context)
@@ -294,6 +308,7 @@ public object WebAuthProvider {
294308
private var ctOptions: CustomTabsOptions = CustomTabsOptions.newBuilder().build()
295309
private var leeway: Int? = null
296310
private var launchAsTwa: Boolean = false
311+
private var customAuthorizeUrl: String? = null
297312

298313
/**
299314
* Use a custom state in the requests
@@ -507,6 +522,18 @@ public object WebAuthProvider {
507522
return this
508523
}
509524

525+
/**
526+
* Specifies a custom Authorize URL to use for this login request, overriding the default
527+
* generated from the Auth0 domain (account.authorizeUrl).
528+
*
529+
* @param authorizeUrl the custom authorize URL.
530+
* @return the current builder instance
531+
*/
532+
public fun withAuthorizeUrl(authorizeUrl: String): Builder {
533+
this.customAuthorizeUrl = authorizeUrl
534+
return this
535+
}
536+
510537
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
511538
internal fun withPKCE(pkce: PKCE): Builder {
512539
this.pkce = pkce
@@ -553,7 +580,8 @@ public object WebAuthProvider {
553580
values[OAuthManager.KEY_ORGANIZATION] = organizationId
554581
values[OAuthManager.KEY_INVITATION] = invitationId
555582
}
556-
val manager = OAuthManager(account, callback, values, ctOptions, launchAsTwa)
583+
val manager = OAuthManager(account, callback, values, ctOptions, launchAsTwa,
584+
customAuthorizeUrl)
557585
manager.setHeaders(headers)
558586
manager.setPKCE(pkce)
559587
manager.setIdTokenVerificationLeeway(leeway)

auth0/src/test/java/com/auth0/android/Auth0Test.java

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import static org.hamcrest.Matchers.is;
2525
import static org.hamcrest.Matchers.notNullValue;
2626
import static org.mockito.Matchers.eq;
27-
import static org.mockito.Mockito.spy;
2827
import static org.mockito.Mockito.when;
2928

3029
import java.lang.reflect.Method;
@@ -157,17 +156,6 @@ public void shouldReturnAuthorizeUrl() {
157156
assertThat(url, hasPath("authorize"));
158157
}
159158

160-
@Test
161-
public void shouldAllowOverridingBuildAuthorizeUrl() {
162-
final String customAuthorizeUrl = "https://custom.example.com/auth";
163-
164-
165-
Auth0 auth0 = Auth0.getInstance(CLIENT_ID, DOMAIN);
166-
Auth0 spyAuth0 = spy(auth0);
167-
when(spyAuth0.buildAuthorizeUrl()).thenReturn(customAuthorizeUrl);
168-
assertThat(spyAuth0.getAuthorizeUrl(), equalTo(customAuthorizeUrl));
169-
}
170-
171159
@Test
172160
public void shouldReturnLogoutUrl() {
173161
Auth0 auth0 = Auth0.getInstance(CLIENT_ID, DOMAIN);
@@ -178,17 +166,6 @@ public void shouldReturnLogoutUrl() {
178166
assertThat(url, hasPath("v2", "logout"));
179167
}
180168

181-
@Test
182-
public void shouldAllowOverridingBuildLogoutUrl() {
183-
final String customLogoutUrl = "https://custom.example.com/logout";
184-
185-
186-
Auth0 auth0 = Auth0.getInstance(CLIENT_ID, DOMAIN);
187-
Auth0 spyAuth0 = spy(auth0);
188-
when(spyAuth0.buildLogoutUrl()).thenReturn(customLogoutUrl);
189-
assertThat(spyAuth0.getLogoutUrl(), equalTo(customLogoutUrl));
190-
}
191-
192169
@Test
193170
public void shouldSetCustomTelemetry() {
194171
Auth0UserAgent customAuth0UserAgent = new Auth0UserAgent("custom", "9.9.9", "1.1.1");
@@ -245,4 +222,4 @@ public void differentConfigShouldReturnDifferentInstances() {
245222
Auth0 auth0_2 = Auth0.getInstance(CLIENT_ID + "2", DOMAIN + "2");
246223
Assert.assertNotSame(auth0, auth0_2);
247224
}
248-
}
225+
}

auth0/src/test/java/com/auth0/android/provider/LogoutManagerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public void setUp() {
3838

3939
@Test
4040
public void shouldCallOnFailureWhenResumedWithCanceledResult() {
41-
LogoutManager manager = new LogoutManager(account, callback, "https://auth0.com/android/my.app.name/callback", customTabsOptions, false, false);
41+
LogoutManager manager = new LogoutManager(account, callback, "https://auth0.com/android/my.app.name/callback", customTabsOptions, false, false,null);
4242
AuthorizeResult result = mock(AuthorizeResult.class);
4343
when(result.isCanceled()).thenReturn(true);
4444
manager.resume(result);
@@ -51,7 +51,7 @@ public void shouldCallOnFailureWhenResumedWithCanceledResult() {
5151

5252
@Test
5353
public void shouldCallOnSuccessWhenResumedWithValidResult() {
54-
LogoutManager manager = new LogoutManager(account, callback, "https://auth0.com/android/my.app.name/callback", customTabsOptions, false, false);
54+
LogoutManager manager = new LogoutManager(account, callback, "https://auth0.com/android/my.app.name/callback", customTabsOptions, false, false,null);
5555
AuthorizeResult result = mock(AuthorizeResult.class);
5656
when(result.isCanceled()).thenReturn(false);
5757
manager.resume(result);

0 commit comments

Comments
 (0)