Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
002b8d6
SDK-6070 flutter changes
NandanPrabhu Jun 25, 2025
ec84b59
method channel for accessing user info
NandanPrabhu Jun 25, 2025
972008a
Merge branch 'main' into SDK-6070
NandanPrabhu Dec 22, 2025
e4acf09
build(deps): bump ruby/setup-ruby from 1.273.0 to 1.274.0 in /.github…
dependabot[bot] Dec 22, 2025
bf858a5
build(deps): bump ruby/setup-ruby from 1.274.0 to 1.275.0 in /.github…
dependabot[bot] Dec 24, 2025
1970f42
build(deps): bump ruby/setup-ruby from 1.275.0 to 1.278.0 in /.github…
dependabot[bot] Jan 4, 2026
e7c7db6
build(deps): bump ruby/setup-ruby from 1.278.0 to 1.279.0 in /.github…
dependabot[bot] Jan 7, 2026
d2db273
build(deps): bump ruby/setup-ruby from 1.279.0 to 1.281.0 in /.github…
dependabot[bot] Jan 13, 2026
8238bfd
build(deps): bump ruby/setup-ruby in /.github/actions/setup-darwin
dependabot[bot] Jan 13, 2026
ae53ba3
build(deps): bump ruby/setup-ruby from 1.282.0 to 1.283.0 in /.github…
dependabot[bot] Jan 15, 2026
7385394
build(deps): bump ruby/setup-ruby from 1.283.0 to 1.285.0 in /.github…
dependabot[bot] Jan 21, 2026
5a97d0a
feat: Add allowedBrowsers parameter to logout API [SDK-724] (#726)
pmathew92 Jan 21, 2026
7df2b95
feat: add custom token exchange support across all platforms
sanchitmehtagit Jan 14, 2026
1051510
fixed test cases
sanchitmehtagit Jan 14, 2026
6fcec69
fixed test cases
sanchitmehtagit Jan 14, 2026
a967065
fix test cases and code refactoring
sanchitmehtagit Jan 14, 2026
2997dc4
refactor
sanchitmehtagit Jan 14, 2026
0fa36df
address feedback
sanchitmehtagit Jan 16, 2026
ae788f7
chore:Fixed errors from flutter analyze (#727)
pmathew92 Jan 21, 2026
e81599b
build(deps-dev): bump lodash from 4.17.21 to 4.17.23 in /appium-test …
dependabot[bot] Jan 22, 2026
721d875
build(deps): bump ruby/setup-ruby from 1.285.0 to 1.286.0 in /.github…
dependabot[bot] Jan 22, 2026
d2ea484
fix flutter analyse errors
sanchitmehtagit Jan 22, 2026
616f589
pubspec update for beta release
sanchitmehtagit Jan 22, 2026
89467e8
Release afpi-v2.0.0-beta.2
sanchitmehtagit Jan 22, 2026
f688cd4
Release af-v2.0.0-beta.2
sanchitmehtagit Jan 22, 2026
7afabd8
udpate podspecs
sanchitmehtagit Jan 22, 2026
e5cf989
udpate pubspec
sanchitmehtagit Jan 22, 2026
fd9e914
make PR runs with release workflow that triggers flutter analyze
sanchitmehtagit Jan 23, 2026
27f7ad7
Avoid running always failing smoke tests for iOS
sanchitmehtagit Jan 23, 2026
9186451
CI cleanup
sanchitmehtagit Jan 23, 2026
e654edc
Resolved merge conflict
pmathew92 Jan 30, 2026
ebd57d9
Renamed getIDTokenContents to user
pmathew92 Jan 30, 2026
1d5246d
Added the code to get profile from android SDK
pmathew92 Jan 30, 2026
2424bf9
Added changes to darwin and other classes
pmathew92 Jan 30, 2026
e39ff33
Added test cases for the user API
pmathew92 Feb 1, 2026
932925c
fixed analyze error
pmathew92 Feb 1, 2026
d825b01
name change in the method handler class
pmathew92 Feb 1, 2026
f43cd21
Fixed the failing test cases
pmathew92 Feb 2, 2026
69688d4
Merge branch 'main' into SDK-6070
pmathew92 Feb 2, 2026
d70d1e1
Fixed the error in analyze due to the branch conflict issue
pmathew92 Feb 2, 2026
ad06a37
fixing swift failures on UTs
pmathew92 Feb 2, 2026
a9cd6ac
Updated the workflow file
pmathew92 Feb 2, 2026
d80cfa8
Minor change
pmathew92 Feb 2, 2026
f6f2bf5
Minor changes from review comments
pmathew92 Feb 2, 2026
c34c152
reverting changes in the Mocks.swift file
pmathew92 Feb 3, 2026
7fde8c3
Reverting the MacOs delegate runner
pmathew92 Feb 3, 2026
3174ce9
updated xcode version to 26.2
pmathew92 Feb 3, 2026
bef9ef2
Removed unwanted code
pmathew92 Feb 3, 2026
b14bb8b
Updated Examples.md file
pmathew92 Feb 3, 2026
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
10 changes: 5 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ jobs:
strategy:
matrix:
xcode:
- '26.0'
- '26.2'

env:
platform: iOS
Expand Down Expand Up @@ -160,7 +160,7 @@ jobs:
with:
name: iOS coverage
path: auth0_flutter/example/ios/cobertura
# TODO: fix both android and iOS smoke testcases and uncomment them.
# TODO: fix both android and iOS smoke testcases and uncomment them.
# test-ios-smoke:
# name: Run native iOS smoke tests using Xcode ${{ matrix.xcode }}
# runs-on: macos-15-large
Expand All @@ -174,7 +174,7 @@ jobs:
# strategy:
# matrix:
# xcode:
# - '26.0'
# - '26.2'

# steps:
# - name: Checkout
Expand Down Expand Up @@ -204,7 +204,7 @@ jobs:
strategy:
matrix:
xcode:
- '26.0'
- '26.2'

env:
platform: macOS
Expand Down Expand Up @@ -247,7 +247,7 @@ jobs:
# strategy:
# matrix:
# xcode:
# - '26.0'
# - '26.2'

# steps:
# - name: Checkout
Expand Down
14 changes: 14 additions & 0 deletions auth0_flutter/EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- [📱 Credentials Manager](#-credentials-manager)
- [Check for stored credentials](#check-for-stored-credentials)
- [Retrieve stored credentials](#retrieve-stored-credentials)
- [Retrieve user profile](#retrieve-user-profile)
- [Custom implementations](#custom-implementations)
- [Local authentication](#local-authentication)
- [Credentials Manager configuration](#credentials-manager-configuration)
Expand Down Expand Up @@ -395,6 +396,7 @@ await webAuth.logout();

- [Check for stored credentials](#check-for-stored-credentials)
- [Retrieve stored credentials](#retrieve-stored-credentials)
- [Retrieve user profile](#retrieve-user-profile)
- [Custom implementations](#custom-implementations)
- [Local authentication](#local-authentication)
- [Credentials Manager configuration](#credentials-manager-configuration)
Expand Down Expand Up @@ -429,6 +431,18 @@ final credentials = await auth0.credentialsManager.credentials();

> 💡 You do not need to call `credentialsManager.storeCredentials()` afterward. The Credentials Manager automatically persists the renewed credentials.

### Retrieve user profile

Fetch the user profile associated with the stored credentials. This method returns `null` if no credentials are present in storage.

```dart
final userProfile = await auth0.credentialsManager.user();

if (userProfile != null) {
print('Email: ${userProfile.email}');
}
```

### Custom implementations

flutter_auth0 exposes a built-in, default Credentials Manager implementation through the `credentialsManager` property. You can pass your own implementation to the `Auth0` constructor. If you're using Web Auth, this implementation will be used to store the user's credentials after login and delete them after logout.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ class Auth0FlutterPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
RenewCredentialsRequestHandler(),
SaveCredentialsRequestHandler(),
HasValidCredentialsRequestHandler(),
ClearCredentialsRequestHandler()
ClearCredentialsRequestHandler(),
GetCredentialsUserInfoRequestHandler()
))
private val dpopCallHandler = Auth0FlutterDPoPMethodCallHandler(listOf(
GetDPoPHeadersApiRequestHandler(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.auth0.auth0_flutter.request_handlers.credentials_manager

import android.content.Context
import com.auth0.android.authentication.storage.SecureCredentialsManager
import com.auth0.auth0_flutter.request_handlers.MethodCallRequest
import com.auth0.auth0_flutter.toMap
import io.flutter.plugin.common.MethodChannel


class GetCredentialsUserInfoRequestHandler: CredentialsManagerRequestHandler {
override val method: String = "credentialsManager#user"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we update the example doc please ignore if already done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have updated the Examples.md file

override fun handle(
credentialsManager: SecureCredentialsManager,
context: Context,
request: MethodCallRequest,
result: MethodChannel.Result
) {
val userProfile = credentialsManager.userProfile
if (userProfile != null) {
result.success(userProfile.toMap())
} else {
result.success(null)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.Context
import android.content.SharedPreferences
import com.auth0.auth0_flutter.request_handlers.credentials_manager.ClearCredentialsRequestHandler
import com.auth0.auth0_flutter.request_handlers.credentials_manager.CredentialsManagerRequestHandler
import com.auth0.auth0_flutter.request_handlers.credentials_manager.GetCredentialsUserInfoRequestHandler
import com.auth0.auth0_flutter.request_handlers.credentials_manager.HasValidCredentialsRequestHandler
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel.Result
Expand Down Expand Up @@ -41,7 +42,16 @@ class CredentialsManagerMethodCallHandlerTest {
val mockResult = mock<Result>()

handler.activity = if (activity === null) mock() else activity
handler.context = if (context === null) mock() else context

val mockContext = if (context === null) {
val ctx: Context = mock()
val mockPrefs: SharedPreferences = mock()
`when`(ctx.getSharedPreferences(any(), any())).thenReturn(mockPrefs)
ctx
} else {
context
}
handler.context = mockContext

handler.onMethodCall(MethodCall(method, arguments), mockResult)
onResult(mockResult)
Expand Down Expand Up @@ -139,7 +149,7 @@ class CredentialsManagerMethodCallHandlerTest {

val managerCaptor = argumentCaptor<com.auth0.android.authentication.storage.SecureCredentialsManager>()
verify(clearCredentialsHandler, times(2)).handle(managerCaptor.capture(), any(), any(), any())

MatcherAssert.assertThat(
"Manager should be reused when configuration is identical",
managerCaptor.firstValue,
Expand Down Expand Up @@ -193,7 +203,7 @@ class CredentialsManagerMethodCallHandlerTest {

val managerCaptor = argumentCaptor<com.auth0.android.authentication.storage.SecureCredentialsManager>()
verify(clearCredentialsHandler, times(2)).handle(managerCaptor.capture(), any(), any(), any())

MatcherAssert.assertThat(
"New manager should be created when domain changes",
managerCaptor.firstValue,
Expand Down Expand Up @@ -233,7 +243,7 @@ class CredentialsManagerMethodCallHandlerTest {
val arguments2 = hashMapOf<String, Any?>(
"_account" to mapOf(
"domain" to "test.auth0.com",
"clientId" to "client-2",
"clientId" to "client-2",
),
"_userAgent" to mapOf(
"name" to "auth0-flutter",
Expand All @@ -245,7 +255,7 @@ class CredentialsManagerMethodCallHandlerTest {

val managerCaptor = argumentCaptor<com.auth0.android.authentication.storage.SecureCredentialsManager>()
verify(clearCredentialsHandler, times(2)).handle(managerCaptor.capture(), any(), any(), any())

MatcherAssert.assertThat(
"New manager should be created when clientId changes",
managerCaptor.firstValue,
Expand Down Expand Up @@ -294,15 +304,15 @@ class CredentialsManagerMethodCallHandlerTest {
"version" to "1.0.0"
),
"credentialsManagerConfiguration" to mapOf(
"android" to mapOf("sharedPreferencesName" to "prefs_2")
"android" to mapOf("sharedPreferencesName" to "prefs_2")
)
)
val call2 = MethodCall("credentialsManager#clearCredentials", arguments2)
handler.onMethodCall(call2, mockResult)

val managerCaptor = argumentCaptor<com.auth0.android.authentication.storage.SecureCredentialsManager>()
verify(clearCredentialsHandler, times(2)).handle(managerCaptor.capture(), any(), any(), any())

MatcherAssert.assertThat(
"New manager should be created when sharedPreferencesName changes",
managerCaptor.firstValue,
Expand Down Expand Up @@ -349,14 +359,14 @@ class CredentialsManagerMethodCallHandlerTest {
"name" to "auth0-flutter",
"version" to "1.0.0"
),
"useDPoP" to true
"useDPoP" to true
)
val call2 = MethodCall("credentialsManager#clearCredentials", arguments2)
handler.onMethodCall(call2, mockResult)

val managerCaptor = argumentCaptor<com.auth0.android.authentication.storage.SecureCredentialsManager>()
verify(clearCredentialsHandler, times(2)).handle(managerCaptor.capture(), any(), any(), any())

MatcherAssert.assertThat(
"New manager should be created when useDPoP flag changes",
managerCaptor.firstValue,
Expand Down Expand Up @@ -414,7 +424,7 @@ class CredentialsManagerMethodCallHandlerTest {

val managerCaptor = argumentCaptor<com.auth0.android.authentication.storage.SecureCredentialsManager>()
verify(clearCredentialsHandler, times(2)).handle(managerCaptor.capture(), any(), any(), any())

MatcherAssert.assertThat(
"New manager should be created when localAuthentication changes",
managerCaptor.firstValue,
Expand All @@ -426,7 +436,7 @@ class CredentialsManagerMethodCallHandlerTest {
fun `handler should reuse manager across different method calls with same configuration`() {
val clearCredentialsHandler = mock<ClearCredentialsRequestHandler>()
val hasValidCredentialsHandler = mock<HasValidCredentialsRequestHandler>()

`when`(clearCredentialsHandler.method).thenReturn("credentialsManager#clearCredentials")
`when`(hasValidCredentialsHandler.method).thenReturn("credentialsManager#hasValidCredentials")

Expand All @@ -451,15 +461,58 @@ class CredentialsManagerMethodCallHandlerTest {

val clearManagerCaptor = argumentCaptor<com.auth0.android.authentication.storage.SecureCredentialsManager>()
val hasValidManagerCaptor = argumentCaptor<com.auth0.android.authentication.storage.SecureCredentialsManager>()

verify(clearCredentialsHandler).handle(clearManagerCaptor.capture(), any(), any(), any())
verify(hasValidCredentialsHandler).handle(hasValidManagerCaptor.capture(), any(), any(), any())

MatcherAssert.assertThat(
"Same manager should be reused across different method calls with identical configuration",
clearManagerCaptor.firstValue,
CoreMatchers.sameInstance(hasValidManagerCaptor.firstValue)
)
}

@Test
fun `handler invokes GetCredentialsUserInfoRequestHandler for credentialsManager#user`() {
val getUserInfoHandler = mock<GetCredentialsUserInfoRequestHandler>()
`when`(getUserInfoHandler.method).thenReturn("credentialsManager#user")

runCallHandler(
"credentialsManager#user",
requestHandlers = listOf(getUserInfoHandler)
) { result ->
verify(getUserInfoHandler).handle(any(), any(), any(), any())
}
}

@Test
fun `handler returns UserProfile result from GetCredentialsUserInfoRequestHandler`() {
val getUserInfoHandler = mock<GetCredentialsUserInfoRequestHandler>()
`when`(getUserInfoHandler.method).thenReturn("credentialsManager#user")

val userProfileMap = mapOf(
"sub" to "auth0|123456",
"name" to "John Doe",
"email" to "[email protected]"
)

doAnswer { invocation ->
val result = invocation.getArgument<Result>(3)
result.success(userProfileMap)
}.`when`(getUserInfoHandler).handle(any(), any(), any(), any())

val mockResult = mock<Result>()
val handler = CredentialsManagerMethodCallHandler(listOf(getUserInfoHandler))
handler.activity = mock()

val mockContext: Context = mock()
val mockPrefs: SharedPreferences = mock()
`when`(mockContext.getSharedPreferences(any(), any())).thenReturn(mockPrefs)
handler.context = mockContext

handler.onMethodCall(MethodCall("credentialsManager#user", defaultArguments), mockResult)

verify(mockResult).success(userProfileMap)
}
}

Loading
Loading