# Security and Authentication

IMS validates the identity of enrolled users via JSON Web Tokens (JWT). The host app is responsible for:

1. Generating a signed JWT via its authentication provider (e.g., your own backend, Firebase, Cognito, or any other auth service).
2. Providing the SDK with a [`TokenSigner`](#token-signer) implementation that retrieves the signed JWT and returns it to the SDK.

The SDK validates that the signed JWT contains all required claims (see [JWT Claims](#jwt-claims)) before using it to make network calls to the IMS backend. Signature verification is performed server-side.

> **Note on the `unsignedToken` parameter:** The `TokenSigner.sign()` method receives an `unsignedToken` parameter. This parameter is **deprecated** and should be **ignored**. The host app is fully responsible for generating its own signed JWT. The `unsignedToken` parameter will be removed in a future SDK version.

***

### JWT Claims

Every signed JWT provided to the SDK must contain the following header and payload claims.

| Claim | Location | Type   | Required | Description                                                                                                                                                                                                                                    |
| ----- | -------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| alg   | Header   | String | Yes      | Signing algorithm. Must be `RS256`.                                                                                                                                                                                                            |
| typ   | Header   | String | Yes      | Token type. Must be `JWT`.                                                                                                                                                                                                                     |
| iss   | Payload  | String | Yes      | Issuer identifier. A unique string identifying the JWT issuer, used for certificate lookup. This value must be unique per environment (e.g., UAT vs. Production) and is coordinated with the IMS team during onboarding.                       |
| sub   | Payload  | String | Yes      | Subject. Must match the user's `enterprise_id` as specified during user enrollment. This value is unique to each user.                                                                                                                         |
| exp   | Payload  | Number | Yes      | Expiration timestamp (seconds since epoch). If the SDK needs to make a network request and the current token is near expiry, a new token will be requested via the `TokenSigner`.                                                              |
| kid   | Header   | String | Optional | Key identifier. Required for some authentication systems (e.g., Firebase). When present, it is used by the IMS backend for certificate lookup. Coordinate with the IMS team during onboarding to determine if this is required for your setup. |
| nbf   | Payload  | Number | Optional | Not-before timestamp (seconds since epoch). If omitted, the SDK falls back to `iat`. Either `nbf` or `iat` must be present.                                                                                                                    |
| iat   | Payload  | Number | Optional | Issued-at timestamp (seconds since epoch). Used as a fallback if `nbf` is not provided.                                                                                                                                                        |
| jti   | Payload  | String | Optional | Unique JWT identifier. Recommended for replay protection.                                                                                                                                                                                      |

#### What the SDK Validates

The SDK performs a lightweight pre-validation before sending the JWT to the IMS backend:

* The signed token has three Base64URL-encoded parts (`header.payload.signature`).
* The payload contains the required claims: `iss`, `sub`, and `exp`.
* The token has not expired.
* If the SDK needs to make a network request and the current token is near expiry, a new token will be requested via the `TokenSigner`.

Claim value validation and cryptographic signature verification are performed server-side by the IMS backend.

***

### Token Signer

The host app must provide the SDK with an implementation of the `TokenSigner` interface (Android) or protocol (iOS).

The implementation should:

1. Request a signed JWT from your authentication provider.
2. Return the signed JWT string via the callback on success.
3. Return an error via the callback on failure.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
interface TokenSigner {
    fun sign(unsignedToken: String, callback: (Result<String>) -> Unit)
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
public protocol TokenSigner {
    func sign(_ unsignedToken: String, resultHandler: @escaping ResultHandler<String>)
}
```

{% endtab %}
{% endtabs %}

#### Example Implementations

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MyTokenSigner : TokenSigner {
    override fun sign(unsignedToken: String, callback: (Result<String>) -> Unit) {
        // Request a signed JWT from your authentication provider.
        // The unsignedToken parameter is deprecated and should be ignored.
        // On success: callback(Result.Success(signedJwt))
        // On failure: callback(Result.Failure(exception))
    }
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
    func sign(_ unsignedToken: String, resultHandler: @escaping ResultHandler<String>) {
        // Request a signed JWT from your authentication provider.
        // The unsignedToken parameter is deprecated and should be ignored.
        // On success: resultHandler(.success(signedJwt))
        // On failure: resultHandler(.failure(error))
    }
}
```

{% endtab %}
{% endtabs %}

***

### SDK Configuration

#### Android

The `TokenSigner` class is provided during SDK configuration. The class **must have a no-argument (empty) constructor** and **must not be obfuscated**.

If using ProGuard or R8, add a keep rule for your `TokenSigner` implementation:

```proguard
-keep class com.yourpackage.MyTokenSigner { *; }
```

```kotlin
if (!ImsSdkManager.isConfigured) {
    ImsSdkManager.setSdkConfiguration(
        context,
        ImsSdkManager.Builder()
            ....
            .setTokenSigner(MyTokenSigner::class.java)
            .build()
    )
}
```

#### iOS

The `TokenSigner` is provided via a factory closure during SDK initialization:

```swift
try initialize(
    ....,
    tokenSignerFactory: { MyTokenSigner() }
)
```

***

### Third-Party Authentication

The SDK supports integration with third-party authentication systems (e.g., Firebase, Cognito). When using a third-party auth provider, certain claim values such as `iss` or `kid` may differ from a standard integration.

Coordinate with the IMS team during onboarding to register the expected claim values for your application. Ensure the signed JWT still contains all required claims as described in [JWT Claims](#jwt-claims).

***

### Security Recommendations

For additional security, consider the following best practices for your host application:

* **Use HTTPS** for all communication between your mobile app and your authentication provider when retrieving signed JWTs.
* **Keep private keys server-side.** The RSA private key used to sign JWTs should never be embedded in the mobile app.
* **Validate user identity before signing.** Your authentication provider should verify that the requesting user is authenticated before issuing a signed JWT. The `sub` claim should match the authenticated user for the current session.
* **Use short-lived tokens.** We recommend keeping token lifetimes short (`exp - nbf` or `exp - iat`). IMS can enforce a maximum token lifetime if desired — contact the IMS team for details.
* **Consider SSL pinning** for communication between your app and your authentication provider.

***

### Backend Setup

Your authentication provider must be configured to sign JWTs using the RS256 algorithm. The corresponding public certificate, or preferably a JWKS URL for automated key rotation, must be provided to IMS during onboarding so the backend can verify token signatures.

For backend integration details, contact the IMS team during your onboarding process.

#### Certificate Format Example

If providing a public certificate (rather than a JWKS URL), use the PEM format as shown below:

```
-----BEGIN CERTIFICATE-----
MIIDrjCCApagAwIBAgIEWUsVMTANBgkqhkiG9w0BAQsFADCBmDEdMBsGCSqGSIb3
DQEJARYOeW91ckBlbWFpbC5jb20xCzAJBgNVBAYTAkNBMRAwDgYDVQQIDAdPbnRh
cmlvMRIwEAYDVQQHDAlLaXRjaGVuZXIxGjAYBgNVBAoMEVlvdXIgT3JnYW5pemF0
aW9uMRQwEgYDVQQLDAtFbmdpbmVlcmluZzESMBAGA1UEAwwJWW91ciBOYW1lMB4X
DTE3MDYyMjAwNTUwMVoXDTE4MDYyMjAwNTUwMVowgZgxHTAbBgkqhkiG9w0BCQEW
DnlvdXJAZW1haWwuY29tMQswCQYDVQQGEwJDQTEQMA4GA1UECAwHT250YXJpbzES
MBAGA1UEBwwJS2l0Y2hlbmVyMRowGAYDVQQKDBFZb3VyIE9yZ2FuaXphdGlvbjEU
MBIGA1UECwwLRW5naW5lZXJpbmcxEjAQBgNVBAMMCVlvdXIgTmFtZTCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAOwEevBh2CzHIJLI94v/gsE9dH43WH+U
/YXGDGm3PTXOOtzca2YLbpGwikXgAePpTEqiH/vhLHYxMXuwhH8a2i3WJHfqV6fK
FBSceC4nHEJuL/KPgW5s2SSmZxHxiGoXaUm2v62HYzO0x8JfR9i3Z7cV+Hn7SBiT
6wOTQaD4+4tLfcnuvF93dzmqF466Bc1ZejPxJYOJrIPKcLA0CZuO1jeGbi/oBGNd
5hMuDAGxfSDBKuiXnJSEocoeSMpiswqs7p4F2vGfiPh9rfmwezPlEhTo/1TGJMzr
K7Iq79ru7a9dg0uiTvDcBWa7pIVvPmjwgHAeYK7l22zysqX0v5xV/+UCAwEAATAN
BgkqhkiG9w0BAQsFAAOCAQEAf/+mKOkC/D0ecRl+HDMJYAW3LPVC0awhRGnRsJtc
c0jB7wPejibsXp+r6aMmK7FCh/H8DKxi2YjO9WGO5N9B346LgzrBAIAt8qJh7Grt
EWG2VDcGTxaI/tLcXbCvZTJFi3Va+NynKYRmnuYhI86jazg7aAl3LwvbYPXZwOMI
zBTw9Izbz4ffnsNrEuY1E1zYF04juJTKZk411WfFaoA33UEhEPYWkfTJNraEmecm
Eaj8nuRPpio0+HAIEBfheDvsIcS7Tov96G8egIMxJAKkKolxL8QCkYhRf4ipztwr
dg7ZGZBMpdKSFQEl3He1A+fsUc3FJYjkMKtvsxRtzAIjIg==
-----END CERTIFICATE-----
```
