> For the complete documentation index, see [llms.txt](https://docs.payments.thalescloud.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.payments.thalescloud.io/3d-secure/ja/d1-sdkwosuru/hajimeni/5.-ren-zheng/sdkroguin.md).

# SDKログイン

## Overview

Before the issuer application calls any D1 SDK service, it must prove that the end user is authenticated.

D1 SDK and D1 backend use this proof to authorize the session.

For example, the issuer application can prompt the end user for biometric authentication.

<figure><img src="/spaces/62lLFDcmLCeqqwmy4Fee/files/tEni9f3QrrCoxSipQitZ" alt=""><figcaption><p>Example: end user biometric authentication.</p></figcaption></figure>

## Login flow

<figure><img src="/spaces/62lLFDcmLCeqqwmy4Fee/files/kFHF1PJcqjo6hZ0mgyEi" alt=""><figcaption><p>SDK login flow.</p></figcaption></figure>

{% hint style="warning" %}
Create the issuer access token with a short expiration time, such as a few minutes. Do not reuse it across multiple login attempts.
{% endhint %}

### Login validity

After login, the end user can access D1 services for the full session.

The default session validity is one hour.

Sensitive D1 services use a shorter validity period. This period is usually a few minutes. If the login is older than that period, the issuer application must authenticate the end user again.

In that case, D1 SDK returns `NOT_LOGGED_IN`.

Prompt the end user to log in again when you receive this error.

### Client binding

Since D1 SDK v4.4.0, client binding strengthens login by binding the issuer access token to the requesting device.

This lets D1 backend verify that later SDK requests come from the authenticated issuer application on the expected device.

With client binding:

* D1 SDK signs each request with device keys.
* D1 backend verifies that the request comes from the registered device.
* Short-lived key pairs reduce the attack surface.

The public key exchange happens during login. This ensures that binding is created only for an authenticated session.

<figure><img src="/spaces/62lLFDcmLCeqqwmy4Fee/files/RcTyILHZx5UzYC7fPzi6" alt=""><figcaption><p>Login flow with client binding.</p></figcaption></figure>

<table><thead><tr><th width="100" align="center">Steps</th><th>Description</th></tr></thead><tbody><tr><td align="center">01 - 02</td><td>Authenticate the end user in the issuer application.</td></tr><tr><td align="center">03 - 05</td><td><p>Call <code>getBindingHash</code> before <code>login</code>.</p><p>The API returns an encoded, hashed client binding payload as a <code>String</code>.</p><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>For iOS integrations, call <code>D1Task.bindingHash()</code> during application startup when possible. Run it in the background. The first call performs the initial binding setup and can take longer. This extra latency usually happens only when iOS binding material is created or refreshed, typically about once every two months.</p></div><p>Send the client binding payload to the issuer backend, do not modify, transform, or re-encode it.</p></td></tr><tr><td align="center">06</td><td><p>Build the issuer access token.</p><p>The issuer backend creates the issuer access token and adds the client binding payload as the <code>cbp</code> claim. See <a href="/spaces/62lLFDcmLCeqqwmy4Fee/pages/SkeH99bh82QvNg8SSPfD">Access token format</a>.</p><div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p>Create the issuer access token with a short expiration time, such as a few minutes. Do not reuse it across multiple login attempts.</p></div></td></tr><tr><td align="center">07 - 09</td><td><p>Call <code>login</code> with the updated issuer access token.</p><p>After login, D1 backend uses the <code>cbp</code> claim for device-binding checks on later SDK requests.</p></td></tr><tr><td align="center">10 - 18</td><td>The issuer application calls any operation and D1 SDK handles the security behind the scene with the D1 backend.</td></tr></tbody></table>

## SDK implementation

Use the following examples.

{% hint style="warning" %}
For iOS devices, the end user must set a device passcode before `bindingHash()` or `login()` is called. Otherwise, D1 SDK returns an error.
{% endhint %}

{% tabs %}
{% tab title="Android Java" %}
{% code lineNumbers="true" %}

```java
public void login(@NonNull D1Task d1Task) throws D1Exception {
    String cbp = d1Task.getBindingHash(); // Must be called if client binding is enabled.
    
    // TODO: replace with the issuer access token returned by your issuer backend. 
    // The token must include cbp as a claim, if client binding is enabled.
    byte[] issuerToken = "<<issuer access token>>".getBytes(); 
    D1Task.Callback<Void> callback = new D1Task.Callback<Void>() {
        @Override
        public void onSuccess(Void ignore) {
            // Proceed with subsequent flows
        }

        @Override
        public void onError(D1Exception exception) {
            // Refer to D1 SDK Integration – Error Management section
        }
    };
    d1Task.login(issuerToken, callback);
}
```

{% endcode %}
{% endtab %}

{% tab title="Android Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
fun login(d1Task: D1Task) {
    val cbp = d1Task.getBindingHash() // Must be called if client binding is enabled.
    
    // TODO: replace with the issuer access token returned by your issuer backend. 
    // The token must include cbp as a claim, if client binding is enabled.
    val issuerToken: ByteArray = "<<issuer access token>>".toByteArray() 
    val callback: D1Task.Callback<Void?> = object : D1Task.Callback<Void?> {

        override fun onSuccess(ignore: Void?) {
            // Proceed with subsequent flows
        }

        override fun onError(exception: D1Exception) {
            // Refer to D1 SDK Integration – Error Management section
        }
    }
    d1Task.login(issuerToken, callback)
}
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code lineNumbers="true" %}

```swift
do {
    let cbp = try await d1Task.bindingHash() // Must be called if client binding is enabled.
    
    // TODO: replace with the issuer access token returned by your issuer backend. 
    // The token must include cbp as a claim, if client binding is enabled.
    var issuerToken = Data()
    try await d1Task.login(&issuerToken)
    // Proceed with subsequent flows
} catch {
    // Refer to D1 SDK Integration – Error Management section
}
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.payments.thalescloud.io/3d-secure/ja/d1-sdkwosuru/hajimeni/5.-ren-zheng/sdkroguin.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
