Skip to content

Latest commit

 

History

History
217 lines (165 loc) · 8.3 KB

MIGRATION.md

File metadata and controls

217 lines (165 loc) · 8.3 KB

Migrating from v1 to v2

v2 replaces the embedded WebView sign-in flow with ASWebAuthenticationSession on iOS. The authentication UI now runs in the system browser context, which enables WebAuthn/passkey sign-in, follows the native-app OAuth guidance in RFC 8252, and shares the browser session by default.

v2 also revamps sign-out to distinguish a complete browser sign-out from a local credential clear, and removes the native social plugin targets that relied on the embedded WebView flow.

Required: review redirect URIs on iOS

In v1, the SDK handled the OAuth redirect inside the embedded WebView. In v2, ASWebAuthenticationSession matches the callback through the redirect URI, so your app must be configured to receive the URI you pass to signInWithBrowser.

Custom scheme redirects

For a custom scheme such as io.logto.app://callback:

  1. Register the scheme in your app's Info.plist. Register only the scheme part, not the full redirect URI. For io.logto.app://callback, the scheme is io.logto.app.
  2. Add the same URI to your Logto application's Redirect URIs.
  3. Pass the same URI to signInWithBrowser.

In Xcode, open your app target, select Info, expand URL Types, and add one entry with io.logto.app in URL Schemes. If you edit Info.plist directly, add:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>io.logto.app</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>io.logto.app</string>
        </array>
    </dict>
</array>
try await logtoClient.signInWithBrowser(
    redirectUri: "io.logto.app://callback"
)

For the browser flow in v2, you do not need to call LogtoClient.handle(url:); that plugin handoff API was removed with the embedded WebView flow.

Custom scheme callbacks can be matched and dismissed automatically on all supported iOS versions.

HTTPS Universal Link redirects

You can also use an HTTPS redirect URI such as https://example.com/callback:

  1. Add the Associated Domains capability to your app.
  2. Configure webcredentials:example.com so ASWebAuthenticationSession can match HTTPS callbacks on iOS 17.4 and newer.
  3. If the same URL should open your app outside the authentication session, also configure applinks:example.com and host a valid apple-app-site-association file.
  4. Add the HTTPS URI to your Logto application's Redirect URIs.
  5. Pass the same URI to signInWithBrowser.

On iOS 17.4 and newer, the SDK uses ASWebAuthenticationSession's HTTPS callback API so HTTPS redirects can automatically complete and dismiss the session. On older iOS versions, the authorization request can still use the HTTPS redirect URI, but the session may not close automatically unless your app handles the Universal Link callback itself. Keep a custom scheme redirect as a compatibility option if you need automatic completion on older iOS versions.

Changed: sign-in behavior

The signInWithBrowser(redirectUri:) API is still the main sign-in entry point:

try await logtoClient.signInWithBrowser(
    redirectUri: "io.logto.app://callback"
)

The visible behavior changes because the flow now uses ASWebAuthenticationSession:

  • iOS may show a system consent prompt before opening the browser session. The prompt text is controlled by the system.
  • Browser cookies are shared by default, so users may get single sign-on behavior across the app and the system browser.
  • To request an isolated browser session, set prefersEphemeralWebBrowserSession: true in LogtoConfig.
  • The app can no longer inspect the page, inject JavaScript, or rely on WebView-only behavior during authentication.

Changed: ID token clock tolerance

ID token verification now tolerates a clock drift of up to 300 seconds between the device and the Logto server (v1 allowed 60 seconds), and the tolerance also applies to the exp claim. This matches the default of the Logto JS SDK. Devices whose clock drifts by more than the tolerance still fail sign-in, with LogtoErrors.Verification.jwtIssuedTimeIncorrect or LogtoErrors.Verification.jwtExpired. These errors are now public, so your app can tell the user to check the device clock.

The tolerance is configurable in seconds through the new idTokenVerification option:

let config = try LogtoConfig(
    endpoint: "<your-logto-endpoint>",
    appId: "<your-app-id>",
    idTokenVerification: IdTokenVerificationOptions(clockTolerance: 600)
)

LogtoConfig throws LogtoClientErrors.Config.invalidClockTolerance if the tolerance is not a positive number of seconds.

Removed: native social plugins

The native social plugin products and targets are removed:

  • LogtoSocialPlugin
  • LogtoSocialPluginWeb
  • LogtoSocialPluginAlipay
  • LogtoSocialPluginWechat

The socialPlugins parameter in LogtoClient initialization and the LogtoClient.handle(url:) / notification-based plugin handoff are also removed.

Social connectors still work through the browser, like on the web. If you depend on the native WeChat or Alipay SDK handoff, stay on the v1 line.

Changed: sign-out API

In v1, signOut() cleared local credentials and tried to revoke the refresh token. It did not end the Logto session cookie because that cookie lived inside the embedded WebView flow.

In v2, that local-only behavior is renamed to clearCredentials(), and signOut(postLogoutRedirectUri:) is a browser-based sign-out that also opens the Logto end session endpoint.

Complete sign-out with redirect

Use this when you have a Post sign-out redirect URI registered in the Logto console. The URI can be a custom scheme or an HTTPS Universal Link. It must also be configured for your iOS app as described above.

let error = await logtoClient.signOut(
    postLogoutRedirectUri: "io.logto.app://signed-out"
)

This clears local credentials, tries to revoke the refresh token, opens the Logto end session endpoint in ASWebAuthenticationSession, and lets Logto navigate back to the app through the post sign-out redirect URI.

Complete sign-out without redirect

Use this when you want to end the Logto browser session but do not have a Post sign-out redirect URI. The browser session stays on the Logto sign-out page and the user returns by dismissing it manually.

let error = await logtoClient.signOut()

Dismissing the browser during sign-out is treated as success. Local credentials have already been cleared before the browser opens, and token revocation has already settled.

Local credential clear

Use this when no UI context is available, such as a background error handler, or when you intentionally only want to clear local state.

let error = await logtoClient.clearCredentials()

This is v1's signOut() behavior: it clears local credentials and tries to revoke the refresh token, but it does not open the browser and does not end the Logto session cookie. The next sign-in may silently re-enter the same account through the browser session. Prefer browser signOut when the user explicitly taps a sign-out button.

Error and retry behavior

  • clearCredentials() and browser signOut return LogtoClientErrors.SignOut?. nil means the local sign-out completed successfully.
  • Token revocation and remote browser sign-out are best effort. If revocation fails, local credentials are still cleared and the revoke error is returned.
  • An invalid postLogoutRedirectUri returns .invalidRedirectUri with no side effects. Credentials stay intact so the caller can fix the URI and retry a complete sign-out.
  • If the browser callback URI does not match the expected post sign-out redirect URI, the SDK returns .unexpectedSignOutCallback.
  • If the browser session cannot start, the SDK returns .unableToLaunchBrowser.

Platform availability

Browser sign-in and browser sign-out are currently available on iOS. On non-iOS platforms, use clearCredentials() for local credential clearing.

Installing v2

v2 is released through Git tags. Select 2.0.0 or a later 2.x version when adding the package in Swift Package Manager or Xcode. The 2.0.0-beta.x prereleases are superseded by the stable release.