as

Settings
Sign out
Notifications
Alexa
Amazonアプリストア
AWS
ドキュメント
Support
Contact Us
My Cases
開発
設計と開発
公開
リファレンス
サポート
アクセスいただきありがとうございます。こちらのページは現在英語のみのご用意となっております。順次日本語化を進めてまいりますので、ご理解のほどよろしくお願いいたします。

useServerChallengeReceived

useServerChallengeReceived is a custom hook that handles mTLS (Mutual TLS) authentication in Kepler apps. This hook manages certificate challenges from servers and provides methods to set client certificates for secure communication.

The following shows how to import the hook.

Copied to clipboard.

import { useServerChallengeReceived } from "@amzn/react-native-kepler";

The following shows how to to use the hook.

Copied to clipboard.

const { isChallengeReceived, setAuthCert, challengeUrl } = useServerChallengeReceived();

AuthCertParams

If you need to provide authentication certificates as part of your server challenge, use the AuthCertParams interface to define them.

interface AuthCertParams {
    url: string;
    clientCert: string;
    clientKey: string;
}

Properties

  • url - The URL for which to set the certificates
  • clientCert - Path to the client certificate file
  • clientKey - Path to the client key file

Hook interface definition

The following shows the hook's return type definition.

export const useServerChallengeReceived = (): {
  /** Counter that increments when a challenge is received */
  isChallengeReceived: number;
  /** Function to set authentication certificates */
  setAuthCert: (params: AuthCertParams) => void;
  /** The URL that initiated the certificate challenge */
  challengeUrl: string;
} => {
  // ... hook implementation
};

Configuration: Required Assets

Network Security Configuration

To provide rootCA certificates, create a network-config.json file in your project's assets/raw directory with the following structure.

Copied to clipboard.

{
    "networkSecurityConfig": {
        "domainConfig": [
            {
                "domain": {
                    "name": "127.0.0.1",
                    "includeSubdomains": true, /* When true, applies to all subdomains */
                    "certificates": "raw/ca.crt"
                }
            }
        ]
    }
}

Note: Replace "127.0.0.1" with your target domain and adjust includeSubdomains as needed. Setting includeSubdomains to true applies the certificate configuration to the main domain and all its subdomains (For example, both example.com and api.example.com). Set it to false to restrict the configuration to only the exact domain specified.

Certificate Files

Place the following certificate files in your application's assets/raw directory.

/assets/raw/
  ├── client.crt    # Client certificate
  ├── client.key    # Client private key
  ├── ca.crt        # Certificate Authority (CA) certificate
  └── network-config.json

The following sample shows a basic mTLS Implementation.

Copied to clipboard.

import { useServerChallengeReceived } from "@amzn/react-native-kepler";
import { useEffect, useState } from "react";
import { Button, StyleSheet, Text, View } from "react-native";

const SERVER1_URL = "https://vs-ws-test-domain.xyz";
const SERVER2_URL = "https://127.0.0.1:3001";

const CLIENT1_CERT = "/raw/client-cert.pem";
const CLIENT1_KEY = "/raw/client-key.pem";
const CLIENT2_CERT = "/raw/client.crt";
const CLIENT2_KEY = "/raw/client.key";

const getDomainFromURL = (input: string): string => {
  if (!input || typeof input !== 'string') {return 'Invalid URL';}
  const url = input.trim();
  const noProtocol = url.replace(/^(https?:\/\/)?/i, '');
  const domainPart = noProtocol.split(/[\/?#]/)[0];
  const domain = domainPart.split(':')[0];

  const domainRegex = /^([a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|localhost|^\d{1,3}(\.\d{1,3}){3})$/;
  return domainRegex.test(domain) ? domain : 'Invalid URL';
};

// State management for responses
const App = () => {
  const [response1, setResponse1] = useState(null);
  const [response2, setResponse2] = useState(null);
  const { isChallengeReceived, setAuthCert, challengeUrl } = useServerChallengeReceived();

  const server1Domain = getDomainFromURL(SERVER1_URL);
  const server2Domain = getDomainFromURL(SERVER2_URL);

  // Function to fetch data
  const fetchData = async (serverUrl, setResponse) => {
    try {
      const response = await fetch(serverUrl, {
        method: "GET",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
        },
      });

      const data = await response.json();
      setResponse(data);
    } catch (error) {
      setResponse({ error: "Request failed. Check logs." });
    }
  };

  // Function to set authentication certificates
  function setCerts(url) {
    try {
      if (url === server1Domain) {
        setAuthCert({
            url: challengeUrl,
            clientCert: CLIENT1_CERT,
            clientKey: CLIENT1_KEY,
          });
      } else if (url === server2Domain) {
        setAuthCert({
            url: challengeUrl,
            clientCert: CLIENT2_CERT,
            clientKey: CLIENT2_KEY,
          });
      } else {
        console.log("Invalid URL for certificate setup");
      }
    } catch (error) {
      console.error("Failed to set certificates:", error);
    }
  }

  // Handle authentication challenges
  useEffect(() => {
    if (isChallengeReceived || challengeUrl) {
      setCerts(challengeUrl);
    }
  }, [isChallengeReceived, challengeUrl]);

  return (
    <View style={styles.container}>
      <View style={styles.section}>
        <Button title="Fetch from Server 1" onPress={() => fetchData(SERVER1_URL, setResponse1)} />
        {response1 && <Text style={styles.response}>Server 1: {JSON.stringify(response1, null, 2)}</Text>}
      </View>

      <View style={styles.section}>
        <Button title="Fetch from Server 2" onPress={() => fetchData(SERVER2_URL, setResponse2)} />
        {response2 && <Text style={styles.response}>Server 2: {JSON.stringify(response2, null, 2)}</Text>}
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {backgroundColor: '#16191f', paddingHorizontal: 5, flex: 1, display: 'flex', alignItems: 'center', overflow: 'hidden'},
  header: { fontSize: 22, fontWeight: "bold", marginBottom: 20 },
  section: { marginVertical: 10, width: "100%", alignItems: "center" },
  response: { marginTop: 10, padding: 10, backgroundColor: "#f0f0f0", borderRadius: 5, width: "90%" },
});

export default App;

Last updated: Sep 30, 2025