# React Native

{% hint style="info" %}
This tutorial is based on the [example app](https://github.com/LanderDK/blitzware-react-native-sdk/tree/master/examples/blitzware-react-native-example).
{% endhint %}

1. [**Configure BlitzWare**](#configure-blitzware)
2. [**Install the BlitzWare React Native SDK**](#id-2-install-the-blitzware-react-native-sdk)
3. [**Implementation Guide**](#id-3-implementation-guide)

## 1) Configure BlitzWare <a href="#configure-blitzware" id="configure-blitzware"></a>

### Get Your Application Keys <a href="#get-your-application-keys" id="get-your-application-keys"></a>

You will need some details about your application to communicate with BlitzWare. You can get these details from the Application Settings section in the BlitzWare dashboard.

<figure><img src="https://3971581513-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYjb41by6V7VaMjHbf8VN%2Fuploads%2FwQUuApkYQcdaekNmrQIy%2Fspa_settings.png?alt=media&#x26;token=33781bdf-97e2-4ad5-aae8-d767017b70a6" alt=""><figcaption></figcaption></figure>

You need the **Client ID**.

### Configure Redirect URIs

A redirect URI is a URL in your application where BlitzWare redirects the user after they have authenticated. The redirect URI for your app must be added to the **Redirect URIs** list in your **Application Settings** under the **Security** tab. If this is not set, users will be unable to log in to the application and will get an error.

## 2) Install the BlitzWare React Native SDK

Run the following command within your project directory to install the [BlitzWare React Native SDK](https://www.npmjs.com/package/blitzware-react-native-sdk):

{% code title="npm" overflow="wrap" lineNumbers="true" %}

```
npm install blitzware-react-native-sdk
```

{% endcode %}

{% code title="yarn" lineNumbers="true" %}

```
yarn add blitzware-react-native-sdk
```

{% endcode %}

### Prerequisites

This SDK requires Expo and the following dependencies:

* `expo-auth-session` - For OAuth 2.0 authentication
* `expo-secure-store` - For secure token storage

If using Expo managed workflow, these are included. For bare React Native, install them separately.

### Platform Setup

#### iOS Setup

1. Add URL scheme to your `app.json` or `app.config.js`:

```json
{
  "expo": {
    "scheme": "yourapp"
  }
}
```

#### Android Setup

The URL scheme in `app.json` automatically configures Android intent filters in Expo managed workflow.

For bare React Native, add to `android/app/src/main/AndroidManifest.xml`:

```xml
<intent-filter android:autoVerify="true">
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="yourapp" />
</intent-filter>
```

## 3) Implementation Guide

Follow this step-by-step guide to implement authentication in your app.

### Step 1: Configure the Provider

Wrap your app with the `BlitzWareAuthProvider` at the root level:

```tsx
import React from 'react';
import { BlitzWareAuthProvider, BlitzWareConfig } from 'blitzware-react-native-sdk';
import { Stack } from 'expo-router';

export default function RootLayout() {
  const blitzWareConfig: BlitzWareConfig = {
    clientId: "your-client-id",
    redirectUri: "yourapp://oauth", // Must match your app scheme
    responseType: "code", // OAuth 2.0 authorization code flow
  };

  return (
    <BlitzWareAuthProvider config={blitzWareConfig}>
      <Stack>
        <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
      </Stack>
    </BlitzWareAuthProvider>
  );
}
```

### Step 2: Basic Authentication

Create your main authentication screen:

```tsx
import React from "react";
import { StyleSheet, Pressable, View, Text } from "react-native";
import { useBlitzWareAuth } from "blitzware-react-native-sdk";

export default function HomeScreen() {
  const { login, logout, isAuthenticated, user, isLoading, error } = useBlitzWareAuth();

  const handleLogin = async () => {
    try {
      await login();
    } catch (error) {
      console.error("Login error:", error);
    }
  };

  const handleLogout = async () => {
    try {
      await logout();
    } catch (error) {
      console.error("Logout error:", error);
    }
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>BlitzWare Authentication</Text>
      
      {/* Authentication Status */}
      <View style={styles.statusContainer}>
        <Text style={styles.subtitle}>Status:</Text>
        <Text>
          {isLoading ? "Loading..." : isAuthenticated ? "Authenticated" : "Not Authenticated"}
        </Text>
        
        {/* Error Display */}
        {error && (
          <View style={styles.errorContainer}>
            <Text style={styles.errorTitle}>Error:</Text>
            <Text style={styles.errorText}>{error.message}</Text>
          </View>
        )}
        
        {/* User Information */}
        {user && (
          <View style={styles.userContainer}>
            <Text style={styles.subtitle}>User Info:</Text>
            <Text>ID: {user.id}</Text>
            <Text>Email: {user.email || "N/A"}</Text>
            <Text>Username: {user.username || "N/A"}</Text>
          </View>
        )}
      </View>
      
      {/* Login/Logout Button */}
      <View style={styles.buttonContainer}>
        {!isAuthenticated ? (
          <Pressable style={styles.button} onPress={handleLogin} disabled={isLoading}>
            <Text style={styles.buttonText}>Login with BlitzWare</Text>
          </Pressable>
        ) : (
          <Pressable style={styles.button} onPress={handleLogout} disabled={isLoading}>
            <Text style={styles.buttonText}>Logout</Text>
          </Pressable>
        )}
      </View>
    </View>
  );
}
```

### Step 3: Advanced Features - Session Validation

Add session validation for enhanced security:

```tsx
import React, { useState } from "react";
import { Alert } from "react-native";
import { useValidateSession } from "blitzware-react-native-sdk";

export default function ProtectedScreen() {
  const { isAuthenticated, user } = useBlitzWareAuth();
  const validateSession = useValidateSession();
  const [sessionValid, setSessionValid] = useState<boolean | null>(null);
  const [validating, setValidating] = useState(false);

  const handleValidateSession = async () => {
    setValidating(true);
    try {
      const isValid = await validateSession();
      setSessionValid(isValid);
      Alert.alert(
        "Session Status",
        isValid ? "Session is valid!" : "Session expired. Please log in again."
      );
    } catch (error) {
      console.error("Session validation error:", error);
      Alert.alert("Error", "Failed to validate session");
    } finally {
      setValidating(false);
    }
  };

  if (!isAuthenticated) {
    return (
      <View style={styles.container}>
        <Text>Please log in to access this content</Text>
      </View>
    );
  }

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Protected Content</Text>
      <Text>Welcome, {user?.username || user?.email}!</Text>
      
      {/* Session Status Display */}
      {sessionValid !== null && (
        <View style={[styles.statusBadge, { 
          backgroundColor: sessionValid ? '#4CAF50' : '#F44336' 
        }]}>
          <Text style={styles.statusText}>
            Session: {sessionValid ? 'Valid' : 'Invalid'}
          </Text>
        </View>
      )}
      
      <Pressable 
        style={styles.button} 
        onPress={handleValidateSession}
        disabled={validating}
      >
        <Text style={styles.buttonText}>
          {validating ? "Validating..." : "Check Session"}
        </Text>
      </Pressable>
    </View>
  );
}
```

### Step 4: Access Token Management

Get access tokens for API calls:

```tsx
import React from "react";
import { Alert } from "react-native";
import { useAccessToken } from "blitzware-react-native-sdk";

export default function ApiScreen() {
  const getAccessToken = useAccessToken();

  const makeApiCall = async () => {
    try {
      // Get the access token (automatically refreshed if needed)
      const token = await getAccessToken();
      
      if (!token) {
        Alert.alert("Error", "No access token available");
        return;
      }

      // Make authenticated API call
      const response = await fetch("https://api.yourservice.com/protected", {
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json',
        },
      });

      if (response.ok) {
        const data = await response.json();
        Alert.alert("Success", "API call successful!");
      } else {
        Alert.alert("Error", "API call failed");
      }
    } catch (error) {
      console.error("API call error:", error);
      Alert.alert("Error", "Failed to make API call");
    }
  };

  const showTokenInfo = async () => {
    try {
      const token = await getAccessToken();
      if (token) {
        Alert.alert(
          "Token Info", 
          `Length: ${token.length} characters\nPreview: ${token.substring(0, 20)}...`
        );
      } else {
        Alert.alert("No Token", "No access token available");
      }
    } catch (error) {
      Alert.alert("Error", "Failed to get token info");
    }
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>API Integration</Text>
      
      <Pressable style={styles.button} onPress={makeApiCall}>
        <Text style={styles.buttonText}>Make Protected API Call</Text>
      </Pressable>
      
      <Pressable style={styles.button} onPress={showTokenInfo}>
        <Text style={styles.buttonText}>Show Token Info</Text>
      </Pressable>
    </View>
  );
}
```

### Step 5: Role-Based Access Control

Implement role-based features:

```tsx
import { Tabs } from "expo-router";
import React from "react";

import { HapticTab } from "@/components/haptic-tab";
import { IconSymbol } from "@/components/ui/icon-symbol";
import { Colors } from "@/constants/theme";
import { useColorScheme } from "@/hooks/use-color-scheme";

import { useBlitzWareAuth } from "blitzware-react-native-sdk";

export default function TabLayout() {
  const colorScheme = useColorScheme();
  const { isAuthenticated, hasRole } = useBlitzWareAuth();
  const isAdmin = hasRole("admin");

  return (
    <Tabs
      screenOptions={{
        tabBarActiveTintColor: Colors[colorScheme ?? "light"].tint,
        headerShown: false,
        tabBarButton: HapticTab,
      }}
    >
      <Tabs.Screen
        name="index"
        options={{
          title: "Home",
          tabBarIcon: ({ color }) => (
            <IconSymbol size={28} name="house.fill" color={color} />
          ),
        }}
      />
      <Tabs.Protected guard={isAuthenticated && isAdmin}>
        <Tabs.Screen
          name="admin"
          options={{
            title: "Admin",
            tabBarIcon: ({ color }) => (
              <IconSymbol size={28} name="person.fill" color={color} />
            ),
          }}
        />
      </Tabs.Protected>
      <Tabs.Screen
        name="explore"
        options={{
          title: "Explore",
          tabBarIcon: ({ color }) => (
            <IconSymbol size={28} name="paperplane.fill" color={color} />
          ),
        }}
      />
    </Tabs>
  );
}
```

```tsx
import React from "react";
import { useHasRole } from "blitzware-react-native-sdk";

export default function Dashboard() {
  const { user } = useBlitzWareAuth();
  const isAdmin = useHasRole('admin');
  const isPremium = useHasRole('premium');

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Dashboard</Text>
      <Text>Welcome, {user?.username}!</Text>
      <Text>Roles: {user?.roles?.join(', ') || 'None'}</Text>
      
      {/* Admin-only content */}
      {isAdmin && (
        <View style={[styles.card, styles.adminCard]}>
          <Text style={styles.cardTitle}>🔧 Admin Panel</Text>
          <Text>You have administrative privileges</Text>
        </View>
      )}
      
      {/* Premium content */}
      {isPremium && (
        <View style={[styles.card, styles.premiumCard]}>
          <Text style={styles.cardTitle}>⭐ Premium Features</Text>
          <Text>Access to premium content</Text>
        </View>
      )}
      
      {/* Regular user content */}
      <View style={styles.card}>
        <Text style={styles.cardTitle}>📊 User Stats</Text>
        <Text>Standard user features available</Text>
      </View>
    </View>
  );
}
```

That's it!
