Authentication

The Zendesk SDK enables secure authentication of end users, allowing agents to reliably verify user identities within Zendesk. Before proceeding with the steps below, ensure you have completed the prerequisites in Authenticating users.

For a practical example, see our demo app repository, which demonstrates user authentication in action.

LoginUser

To authenticate a user, call the loginUser API with a valid JWT (JSON Web Token) generated by your backend. This securely links the end user to their Zendesk identity, enabling agents to verify and personalize their experience.

See Creating a JWT token for details on generating a JWT.

Swift

The result of loginUser can be observed in the optional completionHandler.

Zendesk.instance?.loginUser(with: "your_jwt_here") { result in    switch result {    case .success(let user):        // Handle successful authentication    case .failure(let error):        // Handle authentication failure    }}

Objective-C

Zendesk *instance = [Zendesk instance];
[instance loginUserWith:@"your_jwt_here" completionHandler:^(ZDKZendeskUser * _Nullable user, NSError * _Nullable error) {    // ...}];

Note: During login, if the SDK fails to authenticate the user using loginUser, an unauthenticated user will be created as a fallback. This ensures the user can still access messaging features, but their identity will not be verified until a successful authentication occurs.

Additionally, if your integration uses multiple instances of the Zendesk SDK, each loginUser call will assign a different user to each instance. For more information on switching between SDK instances, see SDK Instances.

LogoutUser

To unauthenticate a user, call the logoutUser API. This will remove the user's authentication and clear their session from the SDK.

Usage:

Swift

The result of logoutUser can be observed in the optional completionHandler.

Zendesk.instance?.logoutUser { result in    switch result {    case .success:        // Handle successful logout    case .failure(let error):        // Handle logout failure    }}

Objective-C

Zendesk *instance = [Zendesk instance];
[instance logoutUserWithCompletionHandler:^(NSError * _Nullable error) {  // ...}];

This function is intended mainly for authenticated users. When an unauthenticated user next accesses the conversation screen after logout, a new user profile and conversation will be created.

Authentication lifecycle

Once loginUser is successful, the user remains authenticated until the token expires, an authentication error occurs, or you explicitly call logoutUser to end the session.

You can create your JWT with an expiration timestamp using the optional exp property. See Creating a JWT token.

Authentication expiration and re-authentication

When the token expires, the server will return a expiredJWT error indicating "The JWT has expired". This error can be captured through the authenticationFailed event listener. When this occurs, you can seamlessly re-authenticate the user by providing a new JWT using the AuthenticationDelegate (recommended), which allows the SDK to refresh the token automatically. If you do not use the delegate, you must manually call loginUser to re-authenticate. If the now unauthenticated user attempts to start a conversation, they will be directed to the conversation screen with an error, and the conversation content will not be visible.

Since the SDK doesn't automatically renew the token, you will have to handle the re-authentication process.

Handling authentication failures with ZendeskEvent.authenticationFailed

You can log any authentication failures from the SDK using ZendeskEvent.authenticationFailed. This is useful for debugging or troubleshooting authentication issues. However, for production apps, it is recommended to use the AuthenticationDelegate for seamless token refresh and re-authentication (see below). The following example demonstrates a manual approach for handling JWT expiry:

Swift

Below is a code sample how to reauthenticate a user after their JWT has expired.

Zendesk.instance?.addEventObserver(self) { event in            switch event {            case .authenticationFailed(let error as NSError):                if error.localizedDescription.contains("The JWT has expired") {                    // Handle logging for event

Using AuthenticationDelegate for token refresh

To simplify handling token expiry and re-authentication, you can use the AuthenticationDelegate. This delegate allows your app to provide a new JWT token when the SDK detects an invalid or expired token, enabling seamless re-authentication for the end user.

Implement the AuthenticationDelegate protocol then initialize and assign the implemented class.

final class ZendeskAuthenticationDelegate: AuthenticationDelegate {    private let authHandler: (@escaping (String) -> Void) -> Void
    init(authHandler: @escaping (@escaping (String) -> Void) -> Void) {        self.authHandler = authHandler    }
    func onInvalidAuth(_ completion: @escaping (String) -> Void) {        authHandler(completion)    }}
Zendesk.authenticationDelegate = ZendeskAuthenticationDelegate { completion in    Task {        // Fetch or generate a new JWT token from your backend        let newJwtToken = fetchNewJwtFromBackend()        // Provide the new token to the SDK        completion(newJwtToken)    }}
  • The onInvalidAuth method is called when the SDK detects an invalid or expired JWT.
  • You should fetch or generate a new JWT from your backend and pass it to the completion handler.
  • This approach ensures the user remains authenticated without manual intervention or interruption to their conversation.

Authentication merges

When the loginUser API identifies that an unauthenticated user in the Zendesk SDK matches an existing user in Zendesk (for example, from previous activity on another device or platform), the SDK will merge the data from both the unauthenticated and authenticated user accounts. For more information, see Merging because of a login event.

This allows a user to start a conversation while unauthenticated and then log in seamlessly, with their conversation history and data combined under their authenticated account.

  • Single-conversation: Once logged in, the user will see that their previous conversation has been combined with conversations from their logged-in account, allowing them to continue seamlessly as an authenticated user.
  • Multi-conversation: Once logged in, the user will see that their previous conversations in the conversation list screen appear alongside the conversations from their logged-in account, providing a unified experience.

Checking the current SDK user and authentication state

Zendesk.getCurrentUser checks the current SDK user and their authentication status at any time. This allows you to determine if the user is authenticated or unauthenticated, and to access the new ZendeskAuthenticationType property on the ZendeskUser object.

Swift

var currentUser = Zendesk.instance?.getCurrentUser()    if currentUser?.authenticationType == .jwt {    // User is authenticated with JWT    } else {    // User is unauthenticated    }

Objective-C

User *currentUser = [[Zendesk instance] getCurrentUser];if (currentUser != nil && currentUser.authenticationType == AuthenticationTypeJWT) {    // User is authenticated with JWT} else {    // User is unauthenticated with JWT}

Common pitfalls & troubleshooting

Token expiry during a conversation

  • If the JWT expires while the user is active, the recommended approach is to use the AuthenticationDelegate. This delegate allows your app to seamlessly provide a new JWT token when the SDK detects an invalid or expired token, ensuring the user remains authenticated without interruption.
  • The SDK will trigger the delegate's onInvalidAuth method, where you should fetch or generate a new JWT from your backend and pass it to the completion handler.
  • This approach provides a robust and user-friendly way to handle token expiry and re-authentication.

Example: Handling token expiry with AuthenticationDelegate

Zendesk.authenticationDelegate = ZendeskAuthenticationDelegate { completion in    Task {        // Fetch or generate a new JWT token from your backend        let newJwtToken = fetchNewJwtFromBackend()        // Provide the new token to the SDK        completion(newJwtToken)    }}
  • The onInvalidAuth method is called when the SDK detects an invalid or expired JWT.
  • You should fetch or generate a new JWT from your backend and pass it to the completion handler.
  • This ensures the user remains authenticated without manual intervention or interruption to their conversation.

User merges when authenticating after unauthenticated use

If a user starts a conversation while unauthenticated and then logs in, Zendesk will attempt to merge the unauthenticated and authenticated user data. For more information, see Merging because of a login event.

This can result in conversation history being combined, which may be confusing if not expected.

  • To avoid unwanted merges, always authenticate users before showing the messaging UI. Ideally, loginUser should be called as soon as the user is logged into your app.
  • If you must allow unauthenticated use, clearly communicate to users that their conversations may be merged upon login.

Best practices for authentication

  • Authenticate Early: Always authenticate users before displaying the messaging screen to avoid unwanted merges and ensure a seamless experience.
  • Check JWT Expiry: Before calling loginUser, check that the JWT is not close to expiry. If it is, generate a new token.
  • Handle Expiry Gracefully: Use the AuthenticationDelegate to automatically handle JWT expiry. When the SDK detects an expired or invalid JWT, the delegate's onInvalidAuth method is triggered, allowing your app to fetch or generate a new JWT from your backend and seamlessly update the user's authentication without interrupting their conversation. This is the recommended approach for robust, user-friendly token refresh.
  • Communicate to Users: If your flow allows starting a conversation while unauthenticated, inform users that their conversations may be merged with their authenticated account later.

FAQ

Q: What happens if my JWT expires during a conversation?

  • A: The SDK emits an AuthenticationFailed event. The recommended approach is to use the AuthenticationDelegate, which allows your app to seamlessly provide a new JWT token and automatically re-authenticate the user without interruption to their conversation.

Q: Why do conversations merge when a user logs in after starting while unauthenticated?

  • A: Zendesk merges the unauthenticated and authenticated user data to provide a seamless experience.

Q: How long does a user stay logged in?

  • A: The user remains authenticated until an authentication error occurs, or you explicitly call logoutUser with a valid JWT. If the user's JWT token is invalidated and a new one cannot be retrieved using the AuthenticationDelegate, the user will also be implicitly logged out and will need to be re-authenticated to regain access to authenticated features.

Q: How can I check if the current user is authenticated or anonymous?
A: Use the new Zendesk.getCurrentUser() API. This returns a ZendeskUser object, which includes the authenticationType property. You can check if authenticationType is authenticated or unauthenticated.

Q: What does Zendesk.getCurrentUser() return if no user is logged in?
A: If no user is logged in, the SDK will return the current unauthenticated user object.

Q: Does the SDK automatically clear user data or create a new anonymous user on authentication failure?
A: No. The SDK now emits an AuthenticationFailed event and maintains the current user state until a valid JWT is provided.

Q: How can I use the current user API to improve my authentication flow?
A: You can check the user's authentication status before displaying sensitive features or prompting for login, and handle authentication state transitions more reliably in your app.