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.

Kotlin

Zendesk.instance.loginUser(    jwt = "your_jwt_here",    successCallback = { user ->        // Handle successful authentication    },    failureCallback = { error ->        // Handle authentication failure    })

Java

Zendesk.getInstance().loginUser("your_jwt_here", new SuccessCallback<ZendeskUser>() {    @Override    public void onSuccess(ZendeskUser user) {        // Handle successful authentication    }}, new FailureCallback<Throwable>() {    @Override    public void onFailure(@NonNull Throwable error) {        // Handle authentication failure    }});

LogoutUser

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

Usage:

Kotlin

Zendesk.instance.logoutUser(    successCallback = {        // Handle successful logout    },    failureCallback = { error ->        // Handle logout failure    })

Java

Zendesk.getInstance().logoutUser(new SuccessCallback<Unit>() {    @Override    public void onSuccess(Unit value) {        // Handle successful logout    }}, new FailureCallback<Throwable>() {    @Override    public void onFailure(@NonNull Throwable error) {        // Handle logout failure    }});

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 ZendeskJwtExpiredException 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 ZendeskAuthenticationDelegate (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 ZendeskAuthenticationDelegate for seamless token refresh and re-authentication (see below). The following example demonstrates a manual approach for handling JWT expiry:

Kotlin

is ZendeskEvent.AuthenticationFailed -> {    if (event.error is ZendeskJwtExpiredException) {        // Handle logging for event    }}

Java

if (zendeskEvent instanceof ZendeskEvent.AuthenticationFailed) {    ZendeskEvent.AuthenticationFailed authFailedEvent = (ZendeskEvent.AuthenticationFailed) zendeskEvent;    if (authFailedEvent.getError() instanceof ZendeskJwtExpiredException) {        // Handle logging for event    }}

Using ZendeskAuthenticationDelegate for token refresh

To simplify handling token expiry and re-authentication, you can use the ZendeskAuthenticationDelegate. 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.

Kotlin

Zendesk.authenticationDelegate = ZendeskAuthenticationDelegate { error, updateToken ->    // Fetch or generate a new JWT token from your backend    val newJwtToken = fetchNewJwtFromBackend()    // Provide the new token to the SDK    updateToken(newJwtToken)}

Java

Zendesk.Companion.setAuthenticationDelegate(   (throwable, updateToken) -> updateToken.invoke(VALID_JWT));
  • 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 updateToken callback.
  • 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 ZendeskAuthenticationType property on the ZendeskUser object.

Kotlin

val currentUser = Zendesk.instance.getCurrentUser()if (currentUser.authenticationType == ZendeskAuthenticationType.Jwt) {    // User is authenticated with JWT} else {    // User is unauthenticated}
Zendesk.instance.getCurrentUser { user ->if (user?.authenticationType == ZendeskAuthenticationType.Jwt) {        // User is authenticated with JWT    } else {       // User is unauthenticated         }}

Java

ZendeskUser currentUser = Zendesk.getInstance().getCurrentUser();if (currentUser.getAuthenticationType() == ZendeskAuthenticationType.JWT) {    // User is authenticated with JWT} else {    // User is anonymous}
Zendesk.getInstance().getCurrentUser(value -> {if (value.getAuthenticationType() == ZendeskAuthenticationType.Jwt) {      // User is authenticated with JWT    } else {      // User is unauthenticated    }});

Common pitfalls & troubleshooting

Token expiry during a conversation

  • If the JWT expires while the user is active, the recommended approach is to use the ZendeskAuthenticationDelegate. 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 updateToken callback.
  • This approach provides a robust and user-friendly way to handle token expiry and re-authentication.

Example: Handling token expiry with ZendeskAuthenticationDelegate

Zendesk.authenticationDelegate = { error, updateToken ->    // Fetch or generate a new JWT token from your backend    val newJwtToken = fetchNewJwtFromBackend()    // Provide the new token to the SDK    updateToken(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 updateToken callback.
  • 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 ZendeskAuthenticationDelegate 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 ZendeskAuthenticationDelegate, 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 ZendeskAuthenticationDelegate, 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.