Skip to content

Commit f471b18

Browse files
Merge branch 'develop/v3.0' into refactor/extract-dpop-credential-validator
2 parents 20d0ff6 + fe630f6 commit f471b18

1 file changed

Lines changed: 2 additions & 141 deletions

File tree

V3_MIGRATION_GUIDE.md

Lines changed: 2 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# v3 Migration Guide
22

3-
> **Note:** This guide is actively maintained during the v3 development phase. As new changes are merged, this document will be updated to reflect the latest breaking changes and migration steps.
4-
53
Auth0.swift v3 includes many significant changes:
64

75
- **Swift 6 concurrency:** Full strict concurrency compliance with `Sendable` conformances, `@MainActor` callbacks, and `@Sendable` closures across all public APIs.
@@ -186,26 +184,6 @@ final class MyLogger: Logger, @unchecked Sendable {
186184

187185
Since custom providers always present UI, they should already be doing UI work on the main thread. In most cases no code changes are required — Swift infers `@Sendable @MainActor` from the `WebAuthProvider` typealias automatically.
188186

189-
<details>
190-
<summary>Migration example</summary>
191-
192-
```swift
193-
// v2
194-
let myProvider: WebAuthProvider = { url, callback in
195-
let agent = MyUserAgent(url: url, callback: callback)
196-
return agent
197-
}
198-
199-
// v3 - Swift infers @Sendable @MainActor from the WebAuthProvider typealias.
200-
// The closure body runs on the main actor, so MyUserAgent.init is called there.
201-
// MyUserAgent does not need to be @MainActor, but it must conform to Sendable.
202-
let myProvider: WebAuthProvider = { url, callback in
203-
let agent = MyUserAgent(url: url, callback: callback)
204-
return agent
205-
}
206-
```
207-
</details>
208-
209187
### @MainActor callback parameters
210188

211189
**Change:** All public callback parameters are now `@MainActor`. This affects the following APIs:
@@ -264,24 +242,6 @@ try await Auth0.webAuth().logout()
264242

265243
- **Custom `WebAuth` conformances (mocks, test doubles)** — Add `@MainActor` to your `start()` and `logout(federated:)` implementations to match the updated protocol requirement.
266244

267-
<details>
268-
<summary>Migration example</summary>
269-
270-
```swift
271-
// v2
272-
struct MockWebAuth: WebAuth {
273-
func start() async throws -> Credentials { ... }
274-
func logout(federated: Bool) async throws { ... }
275-
}
276-
277-
// v3
278-
struct MockWebAuth: WebAuth {
279-
@MainActor func start() async throws -> Credentials { ... }
280-
@MainActor func logout(federated: Bool) async throws { ... }
281-
}
282-
```
283-
</details>
284-
285245
- **Callers using `any WebAuth` (protocol existential)** — The `@MainActor` constraint is now enforced at the call site through the protocol. Under strict concurrency, Swift will emit a warning if you call these methods from a non-isolated context without `await`.
286246

287247
---
@@ -686,10 +646,8 @@ credentialsManager.credentials { result in
686646
switch error {
687647
case .dpopNotConfigured:
688648
// Developer forgot to call useDPoP() on the Authentication client
689-
// passed to the credentials manager. Fix the client configuration.
690-
```swift
691-
CredentialsManager(authentication: Auth0.authentication().useDPoP())
692-
```swift
649+
// passed to the credentials manager. Fix the client configuration:
650+
// CredentialsManager(authentication: Auth0.authentication().useDPoP())
693651
case .dpopKeyMissing:
694652
// DPoP key was lost. Clear local state and prompt user to re-authenticate
695653
case .dpopKeyMismatch:
@@ -905,27 +863,6 @@ Auth0.swift will use a current key window to present the in-app browser for Web
905863
- `presentationWindow(_ window:)`
906864
- `useCredentialsManager(_ credentialsManager:)` — Use a `CredentialsManager` instance for automatic credential storage and clearing.
907865

908-
<details>
909-
<summary>Code</summary>
910-
911-
```swift
912-
Auth0
913-
.webAuth()
914-
.presentationWindow(window)
915-
.start { result in
916-
// ...
917-
}
918-
919-
// Use a CredentialsManager for automatic credential storage
920-
Auth0
921-
.webAuth()
922-
.useCredentialsManager(credentialsManager)
923-
.start { result in
924-
// ...
925-
}
926-
```
927-
</details>
928-
929866
### Credentials Manager clearAll
930867

931868
**New method:** `clearAll() throws` has been added to `CredentialsManager`.
@@ -934,18 +871,6 @@ This method removes **all** entries managed by the Credentials Manager from the
934871

935872
This is different from the existing `clear()` method, which only removes the default credentials entry.
936873

937-
<details>
938-
<summary>Code</summary>
939-
940-
```swift
941-
// Clear only the default credentials entry (existing method)
942-
try credentialsManager.clear()
943-
944-
// Clear ALL keychain entries managed by the Credentials Manager (new method)
945-
try credentialsManager.clearAll()
946-
```
947-
</details>
948-
949874
**Impact:** This is a new additive API. No migration is required. Use it when you need to completely wipe all stored credentials (e.g., on account deletion or full sign-out).
950875

951876
### CredentialsStorage deleteAllEntries
@@ -1020,80 +945,18 @@ The following APIs have been renamed to align with the Android, Flutter, and Rea
1020945

1021946
The `clearSession(federated:)` method on the Web Auth client has been renamed to `logout(federated:)`. This affects all three API flavors: callback-based, Combine, and async/await.
1022947

1023-
<details>
1024-
<summary>Migration example</summary>
1025-
1026-
```swift
1027-
// v2
1028-
Auth0
1029-
.webAuth()
1030-
.clearSession { result in
1031-
// ...
1032-
}
1033-
1034-
try await Auth0.webAuth().clearSession()
1035-
1036-
// v3
1037-
Auth0
1038-
.webAuth()
1039-
.logout { result in
1040-
// ...
1041-
}
1042-
1043-
try await Auth0.webAuth().logout()
1044-
```
1045-
</details>
1046-
1047948
**`UserInfo``UserProfile`**
1048949

1049950
The `UserInfo` struct has been renamed to `UserProfile`. The `userInfo(withAccessToken:)` method name on the Authentication client is unchanged, as it maps to the OIDC `/userinfo` endpoint.
1050951

1051-
<details>
1052-
<summary>Migration example</summary>
1053-
1054-
```swift
1055-
// v2
1056-
let user: UserInfo = ...
1057-
1058-
// v3
1059-
let user: UserProfile = ...
1060-
```
1061-
</details>
1062-
1063952
**`expiresIn``expiresAt`**
1064953

1065954
The `expiresIn` property on `Credentials`, `APICredentials`, and `SSOCredentials` has been renamed to `expiresAt`. The JSON key (`expires_in`) and Keychain storage key are unchanged.
1066955

1067-
<details>
1068-
<summary>Migration example</summary>
1069-
1070-
```swift
1071-
// v2
1072-
let expiry = credentials.expiresIn
1073-
1074-
// v3
1075-
let expiry = credentials.expiresAt
1076-
```
1077-
</details>
1078-
1079956
**`Telemetry``Auth0ClientInfo`**
1080957

1081958
The `Telemetry` struct has been renamed to `Auth0ClientInfo`, and the `telemetry` property on `Trackable` conforming types has been renamed to `auth0ClientInfo`.
1082959

1083-
<details>
1084-
<summary>Migration example</summary>
1085-
1086-
```swift
1087-
// v2
1088-
var auth = Auth0.authentication()
1089-
auth.telemetry.enabled = false
1090-
1091-
// v3
1092-
var auth = Auth0.authentication()
1093-
auth.auth0ClientInfo.enabled = false
1094-
```
1095-
</details>
1096-
1097960
### Request to Requestable
1098961

1099962
**Change:** All `Authentication` and `MFAClient` methods now return protocol types instead of the concrete `Request` struct:
@@ -1240,7 +1103,5 @@ For example, if you were reading or updating user metadata:
12401103
2. **Call that endpoint from your app**, passing the user's access token as a `Bearer` token in the `Authorization` header.
12411104
3. **On your backend**, obtain a machine-to-machine token via the [Client Credentials flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-credentials-flow) and use it to call the [Management API](https://auth0.com/docs/api/management/v2) with the precise scopes required.
12421105

1243-
**Reason:** The Management API is not designed for direct use from mobile apps — it is heavily restricted for public clients (only a small subset of operations are permitted, and sensitive actions such as managing roles, rules, or other users are not available). It also requires its own audience (`https://YOUR_AUTH0_DOMAIN/api/v2/`), and each individual access token is scoped to a single audience. If your app also needs to call your own backend API, you must set that API's identifier as the audience at login, which means the same token cannot be used for the Management API.
1244-
12451106
---
12461107
[Go up ⤴](#table-of-contents)

0 commit comments

Comments
 (0)