Authenticating end users
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 theupdateToken
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'sonInvalidAuth
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 theZendeskAuthenticationDelegate
, 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 theZendeskAuthenticationDelegate
, 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.