# 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="/files/2wZRoRqdmWpuTXY4PW2j" 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!


---

# Agent Instructions: 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:

```
GET https://docs.blitzware.xyz/oauth/quickstart/native/react-native.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
