> ## Documentation Index
> Fetch the complete documentation index at: https://moengage.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# JWT Authentication

> Secure your MoEngage data collection by implementing JWT authentication in your iOS application.

## Overview

JWT (JSON Web Token) authentication is a standard method for securely verifying user identity. By implementing JWT authentication, you add a critical layer of security to your data collection process with MoEngage.

The feature ensures that the data sent on behalf of your identified users is authentic and has not been tampered with. This security is achieved by requiring a token that is cryptographically signed by your own server, which prevents unauthorized users from impersonating your legitimate users.

<Note>
  **Prerequisites**

  Before you begin the implementation, please ensure you meet the following requirements:

  * Your application must use the MoEngage iOS SDK version ***10.08.0*** or higher to access the JWT authentication feature.
  * You must have access to your MoEngage dashboard to manage public keys and configure the feature's enforcement settings.
</Note>

The following diagram illustrates the interaction between your application, your server, the MoEngage SDK, and the MoEngage server:

<img src="https://mintcdn.com/moengage/Jtvf10ggM77HdKvB/images/jwt1.jpeg?fit=max&auto=format&n=Jtvf10ggM77HdKvB&q=85&s=052d9b91b5df29a78bc667f6d22f1fb4" alt="Jwt1" width="1399" height="706" data-path="images/jwt1.jpeg" />

## Integration

Follow these steps to integrate JWT authentication into your iOS application.

### Step 1: Enable JWT Authentication

You can enable JWT authentication during [SDK initialization](/developer-guide/ios-sdk/sdk-integration/basic/sdk-initialization) by configuring the [***networkConfig***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKConfig.html#/c:@M@MoEngageCore@objc\(cs\)MoEngageSDKConfig\(py\)networkConfig).[***authorizationConfig***](https://moengage.github.io/ios-api-reference/Classes/MoEngageNetworkRequestConfig.html#/c:@M@MoEngageCore@objc\(cs\)MoEngageNetworkRequestConfig\(py\)authorizationConfig) property on the [***MoEngageSDKConfig***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKConfig.html) object.

<CodeGroup>
  ```swift Swift wrap theme={null}
  let sdkConfig = MoEngageSDKConfig(appId: "", dataCenter: .YOUR_DATA_CENTER)
  sdkConfig.networkConfig = MoEngageNetworkRequestConfig(authorizationConfig: MoEngageNetworkAuthorizationConfig(isJwtEnabled: true))
  #if DEBUG
  MoEngage.sharedInstance.initializeDefaultTestInstance(sdkConfig)
  #else
  MoEngage.sharedInstance.initializeDefaultLiveInstance(sdkConfig)
  #endif
  ```

  ```objective-c Objective C wrap theme={null}
  MoEngageSDKConfig* sdkConfig = [[MoEngageSDKConfig alloc] initWithAppId:@"" dataCenter:YOUR_DATA_CENTER];
  sdkConfig.networkConfig = [[MoEngageNetworkRequestConfig alloc] initWithAuthorizationConfig:[[MoEngageNetworkAuthorizationConfig alloc] initWithIsJwtEnabled:YES]];
  #ifdef DEBUG
  [[MoEngage sharedInstance] initializeDefaultTestInstance:sdkConfig];
  #else
  [[MoEngage sharedInstance] initializeDefaultLiveInstance:sdkConfig];
  #endif
  ```
</CodeGroup>

### Step 2: Pass the JWT to the SDK

Your application is responsible for managing the JWT lifecycle. The recommended flow is to fetch a token upon user login and pass the token to the SDK. You should also check if the token has expired on subsequent app launches and fetch a new one if necessary.

Use the [***MoEngageSDKCore.passAuthenticationDetails()***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCore.html#/c:@CM@MoEngageCore@objc\(cs\)MoEngageSDKCore\(im\)passAuthenticationDetails:workspaceId:) method to provide the token to the SDK.

<Warning>
  * `MoEngageSDKCore.sharedInstance.passAuthenticationDetails` requires JWT to be enabled in `MoEngageNetworkAuthorizationConfig` during SDK initialization (Step 1 above). Calling this method without first enabling JWT throws a fatal exception and crashes the app in `DEBUG` builds. In release builds, the call is dropped silently and the token is not registered with the SDK.
  * If you are upgrading an existing app and these strict `DEBUG` validations cause disruptive crashes while you refactor your tracking code, you can temporarily opt out by calling `disableIntegrationValidator()` during SDK initialization. Use this strictly as a stopgap for phased upgrades, and aim to remove the opt-out once your attribute call sites are properly validated.
</Warning>

<Info>
  In the iOS SDK, `DEBUG` mode means the SDK was initialized using `initializeDefaultTestInstance(_:)` (TEST workspace) and the app is running attached to Xcode. This is different from a release build that has debug symbols enabled.
</Info>

<CodeGroup>
  ```swift Swift wrap theme={null}
  let jwtDetails = MoEngageJwtAuthenticationDetails(token: "your_jwt_token", identifier: "user_id")
  MoEngageSDKCore.sharedInstance.passAuthenticationDetails(jwtDetails)
  ```

  ```objective-c Objective C wrap theme={null}
  MoEngageJwtAuthenticationDetails* jwtDetails = [[MoEngageJwtAuthenticationDetails alloc] initWithToken:@"your_jwt_token" identifier:@"user_id"];
  [[MoEngageSDKCore sharedInstance] passAuthenticationDetails:jwtDetails];
  ```
</CodeGroup>

### Step 3: Handle Authentication Errors

To handle token validation errors that the MoEngage server returns, you must register an error listener using [***MoEngageSDKCore.registerAuthenticationListener()***](https://moengage.github.io/ios-api-reference/Classes/MoEngageSDKCore.html#/c:@CM@MoEngageCore@objc\(cs\)MoEngageSDKCore\(im\)registerAuthenticationListener:workspaceId:) method. The SDK invokes this listener when an authentication error occurs, which allows your application to fetch and provide a new token.

<CodeGroup>
  ```swift Swift wrap theme={null}
  class JwtAuthenticationListener: NSObject, MoEngageAuthenticationError.Listener {
      func onError(_ error: MoEngageAuthenticationError) {
          print("Authentication Error Received:")
          if let jwtError = error as? MoEngageJwtAuthenticationError {
              print("- Code: \(jwtError.details.code.rawValue) - \(jwtError.details.code.description)")
              print("- Token: \(jwtError.details.token == nil ? "No token" : String(jwtError.details.token!.prefix(20)) + "...")")
              print("- Identifier: \(jwtError.details.identifier == nil ? "No identifier" : jwtError.details.identifier!)")
              print("- Message: \(jwtError.details.message ?? "No message")")
          } else {
              print("- Message: \(error.details.message ?? "No message")")
          }
          print("- Account: \(error.accountMeta.appID)")
      }
  }
  // Register listner after SDK initialization
  let listener = JwtAuthenticationListener()
  MoEngageSDKCore.sharedInstance.registerAuthenticationListener(listener)
  ```

  ```objective-c Objective C wrap theme={null}
  @interface JwtAuthenticationListener : NSObject 
  @end

  @implementation JwtAuthenticationListener

  - (void)onError:(MoEngageAuthenticationError *)error {
      NSLog(@"Authentication Error Received:");
      if ([error isKindOfClass:[MoEngageJwtAuthenticationError class]]) {
          MoEngageJwtAuthenticationError *jwtError = (MoEngageJwtAuthenticationError *)error;
          NSLog(@"- Code: %ld - %@", (long)jwtError.details.code.rawValue, jwtError.details.code.description);
          NSString *tokenDisplay = jwtError.details.token ? 
              [[jwtError.details.token substringToIndex:MIN(20, jwtError.details.token.length)] stringByAppendingString:@"..."] : 
              @"No token";
          NSLog(@"- Token: %@", tokenDisplay);
          NSLog(@"- Identifier: %@", jwtError.details.identifier ?: @"No identifier");
          NSLog(@"- Message: %@", jwtError.details.message ?: @"No message");
      } else {
          NSLog(@"- Message: %@", error.details.message ?: @"No message");
      }
      NSLog(@"- Account: %@", error.accountMeta.appID);
  }
  @end
  // 
  JwtAuthenticationListener *listener = [[JwtAuthenticationListener alloc] init];
  [[MoEngageSDKCore sharedInstance] registerAuthenticationListener:listener];
  ```
</CodeGroup>

### Step 4: Register the listener after SDK initialization

Register the [***MoEngageAuthenticationError.Listener***](https://moengage.github.io/ios-api-reference/Classes/MoEngageAuthenticationError/Listener.html) in a global scope, such as the ***applicaton(\_:didFinishLaunchingWithOptions:)*** method of your AppDelegate class, to ensure your application always receives callbacks.

<CodeGroup>
  ```swift Swift wrap theme={null}
  let listener = JwtAuthenticationListener()
  MoEngageSDKCore.sharedInstance.registerAuthenticationListener(listener)
  ```

  ```objective-c Objective C wrap theme={null}
  JwtAuthenticationListener *listener = [[JwtAuthenticationListener alloc] init];
  [[MoEngageSDKCore sharedInstance] registerAuthenticationListener:listener];
  ```
</CodeGroup>

<Info>
  **Information**

  * If an API request fails due to an authentication error, the SDK will not retry the request until your application provides a new token.
  * After 10 consecutive authentication failures in a single session, the SDK will stop attempting to sync data until the next session begins. This counter resets after any successful sync.
  * Upon user logout, if a data sync fails due to a JWT error, the pending data will be deleted, and no retry will be attempted.
</Info>
