# SignIn.SocialLogins

Canonical page: https://docs.ovok.com/native-sdk/guide/components/auth/sign-in/social-logins

Container component that groups social login buttons with consistent horizontal layout and spacing.

## Provider requirement [#provider-requirement]

The social-login buttons use the SDK theme for spacing, colors and typography. Render them inside
the SDK `ThemeProvider` (usually imported as `ThemeProvider as OvokThemeProvider`) and the
`OvokProvider` from `@ovok/core/next/react`, as shown in the installation guide. A cancelled Apple prompt is
treated as a cancellation and does not call `onError`; successful login sessions retain both the
FHIR reference and its display value.

## Prerequisites [#prerequisites]

Before using social login components, you need to complete the following setup steps:

### Google Login Setup [#google-login-setup]

1. **Get Google Credentials**: Obtain your Google client ID and iOS URL scheme from [Google Cloud Console](https://console.cloud.google.com/). For further information please follow [this guide](https://react-native-google-signin.github.io/docs/setting-up/get-config-file?firebase-or-not=cloud-console#ios)
2. **Configure App**: Update your `app.config.js` or `app.json` with the Google Sign-In plugin:

```javascript
// app.config.js
export default {
  expo: {
    plugins: [
      [
        "@react-native-google-signin/google-signin",
        {
          iosUrlScheme: "com.googleusercontent.apps.YOUR_CLIENT_ID",
        },
      ],
    ],
  },
};
```

For detailed Google Sign-In configuration, see the [Installation Guide](/native-sdk/guide/how-to/installation).

### Apple Login Setup [#apple-login-setup]

Apple authentication requires the Apple authentication plugin and a native rebuild.
See the [Installation Guide](/native-sdk/guide/how-to/installation).

### Ovok Dashboard Configuration [#ovok-dashboard-configuration]

Both Google and Apple login methods require configuration in the [Ovok Dashboard](https://dashboard.ovok.com/):

1. **Navigate** to the Ovok Dashboard
2. **Update or Create** a ClientApplication with the following extension configuration:

```json
{
  "extension": [
    {
      "url": "https://api.ovok.com/fhir/StructureDefinition/external-auth-internal-id",
      "valueString": "google-web-app-id",
      "extension": [
        {
          "url": "https://api.ovok.com/fhir/StructureDefinition/external-auth-client-id",
          "valueString": "605727522930-c06g9o9f4t906fqt9bkg6sncdn4lb504.apps.googleusercontent.com"
        },
        {
          "url": "https://api.ovok.com/fhir/StructureDefinition/external-auth-provider-type",
          "valueString": "google"
        }
      ]
    }
  ]
}
```

**Configuration Values:**

- **`external-auth-internal-id`**: Custom identifier for matching (use this value in the `internalId` prop)
- **`external-auth-client-id`**:
  - For Google: Your Google client ID from Google Cloud Console
  - For Apple: Your app's bundle identifier, or the Services ID for the web entry
- **`external-auth-provider-type`**: Set to `"google"` or `"apple"`

### Native client configuration [#native-client-configuration]

After configuring the ClientApplication in the Ovok Dashboard, pass its ID as `clientId` to the native client:

```tsx
// app/_layout.tsx
import { Ovok } from "@ovok/native/next";
import * as SecureStore from "expo-secure-store";

const ovokClient = new Ovok({
  baseUrl: "https://api.example.com",
  tenantCode: "your-tenant",
  secureStore: SecureStore,
  clientId: "YOUR_CLIENT_APPLICATION_ID",
});
```

**Important:** Replace `YOUR_CLIENT_APPLICATION_ID` with the actual ClientApplication ID from your Ovok Dashboard configuration.

## Sign in on the web [#sign-in-on-the-web]

On React Native Web the same buttons work with no extra setup in the bundle. The SDK ships web versions of
`GoogleLogin` and `AppleLogin` (`.web` platform files), so a web bundle never loads
`@react-native-google-signin/google-signin` or `expo-apple-authentication`. The buttons look and compose as on a phone;
the web needs these props in addition:

| Button | Web prop | Meaning |
| --- | --- | --- |
| `GoogleLogin` | `googleWebClientId` | The Google **Web application** client ID. `googleIosClientId` is ignored. |
| `GoogleLogin` | `googleRedirectUri` | Optional. The page Google returns to; defaults to `/oauth/google.html` on your site. |
| `AppleLogin` | `appleServicesId` | The Apple **Services ID**. Without it the button renders nothing on the web. |
| `AppleLogin` | `appleRedirectUri` | Optional. A Return URL of the Services ID; defaults to your site's origin. |

### Google on the web [#google-on-the-web]

Google signs the user in with an OpenID Connect redirect in the same tab: the page goes to Google, Google returns to a
static page of yours, and that page sends the tab back to the sign-in screen. Keep `GoogleLogin` on that screen: when it
mounts, it takes Google's answer, checks that it answers this tab's own request, and signs in.

**1. Authorize the redirect URI.** In the [Google Cloud Console](https://console.cloud.google.com/), open the OAuth
client of type **Web application** and add the return page to **Authorized redirect URIs**, for example
`https://app.example.com/oauth/google.html` (and `http://localhost:8081/oauth/google.html` for local development).

**2. Serve the return page as a static file.** The SDK exports its HTML as `GOOGLE_RETURN_PAGE_HTML`, and
`@ovok/native/auth/google-return-page` loads in plain Node, so a build step can write it into the folder your app serves,
such as Expo's `public/`:

```js
// scripts/write-google-return-page.cjs
const { mkdirSync, writeFileSync } = require("node:fs");
const { GOOGLE_RETURN_PAGE_HTML } = require("@ovok/native/auth/google-return-page");

mkdirSync("public/oauth", { recursive: true });
writeFileSync("public/oauth/google.html", GOOGLE_RETURN_PAGE_HTML);
```

Run it before the web build, for example as `"prebuild:web": "node scripts/write-google-return-page.cjs"`. To serve the page
somewhere else, register that URL and pass it as `googleRedirectUri`.

**3. Point Ovok at the Web client.** The `external-auth-client-id` of the Google entry is the Web client ID, and its
`external-auth-internal-id` is the `internalId` you pass to `GoogleLogin`.

The page keeps Google's answer in the tab's `sessionStorage` and replaces itself with the screen the user left, so the
ID token never stays in the address bar or the history. The button accepts the answer only when its `state` and its
token's `nonce` match the request this tab made, and it clears both from storage either way.

### Apple on the web [#apple-on-the-web]

Apple signs the user in with Sign in with Apple JS in a popup. The button loads Apple's script when it mounts, so the
popup opens straight from the tap.

**1. Create a Services ID.** In the [Apple Developer account](https://developer.apple.com/account/resources/identifiers/list/serviceId),
create a **Services ID** and enable Sign in with Apple for it. Under **Configure**, choose the primary App ID and add your
domain and the Return URL, for example `app.example.com` and `https://app.example.com`. The Return URL is `appleRedirectUri`,
which defaults to the site's origin. Apple does not accept `localhost`, so test on an HTTPS domain registered for the
Services ID.

**2. Add a separate Ovok entry for the Services ID.** Apple's web tokens have the Services ID as their audience, while the
iOS app's tokens have its bundle ID, so one entry cannot verify both. Add the entry to the ClientApplication's
`extension` array, and pass its `internalId` to `AppleLogin` on the web:

```json
{
  "url": "https://api.ovok.com/fhir/StructureDefinition/external-auth-internal-id",
  "valueString": "apple-web",
  "extension": [
    {
      "url": "https://api.ovok.com/fhir/StructureDefinition/external-auth-client-id",
      "valueString": "com.example.web"
    },
    {
      "url": "https://api.ovok.com/fhir/StructureDefinition/external-auth-provider-type",
      "valueString": "apple"
    }
  ]
}
```

A closed popup and a declined authorization are cancellations and do not call `onError`. Apple sends the name and email
only the first time a user signs in with your app.

### One screen for every platform [#one-screen-for-every-platform]

```tsx
import { Platform } from "react-native";

<SignIn.SocialLogins.GoogleLogin
  googleIosClientId={googleIosClientId}
  googleWebClientId={googleWebClientId}
  internalId="google"
>
  <SignIn.SocialLogins.GoogleLogin.Icon />
  <SignIn.SocialLogins.GoogleLogin.Text />
</SignIn.SocialLogins.GoogleLogin>

<SignIn.SocialLogins.AppleLogin
  internalId={Platform.OS === "web" ? "apple-web" : "apple"}
  appleServicesId={appleServicesId}
>
  <SignIn.SocialLogins.AppleLogin.Icon />
  <SignIn.SocialLogins.AppleLogin.Text />
</SignIn.SocialLogins.AppleLogin>
```

`useSocialSignIn` has no web flow and rejects on the web; render the buttons instead.

## Quick Example [#quick-example]

```tsx
import { SignIn, useAppTheme } from "@ovok/native";
import React from "react";
import { Alert, StyleSheet } from "react-native";

// Static styles outside component
const styles = StyleSheet.create({
  socialContainer: {
    alignItems: "center",
  },
});

const SocialLoginSection = () => {
  const theme = useAppTheme();

  const handleSuccess = () => Alert.alert("Signed in");

  const handleError = (error: Error) => Alert.alert("Sign-in failed", error.message);

  return (
    <SignIn.SocialLogins
      style={[
        styles.socialContainer,
        {
          marginVertical: theme.spacing(3),
        },
      ]}
    >
      <SignIn.SocialLogins.GoogleLogin
        googleIosClientId="your-ios-client-id.googleusercontent.com" // This will be used for ios devices
        googleWebClientId="your-web-client-id.googleusercontent.com" // This will be used for android devices
        internalId="google-login" // This is the name that you add in extension of ClientApplication for google provider
        onSuccess={handleSuccess}
        onError={handleError}
      >
        <SignIn.SocialLogins.GoogleLogin.Icon />
        <SignIn.SocialLogins.GoogleLogin.Text>
          Continue with Google
        </SignIn.SocialLogins.GoogleLogin.Text>
      </SignIn.SocialLogins.GoogleLogin>

      <SignIn.SocialLogins.AppleLogin
        internalId="apple-login" // This is the name that you add in extension of ClientApplication for apple provider
        onSuccess={handleSuccess}
        onError={handleError}
      >
        <SignIn.SocialLogins.AppleLogin.Icon />
        <SignIn.SocialLogins.AppleLogin.Text>
          Continue with Apple
        </SignIn.SocialLogins.AppleLogin.Text>
      </SignIn.SocialLogins.AppleLogin>
    </SignIn.SocialLogins>
  );
};

export default SocialLoginSection;
```

## Props [#props]

Every prop, with its type and description, is listed in the [`@ovok/native/auth` API reference](/native-sdk/reference/auth).

## Component Behavior [#component-behavior]

The component uses horizontal layout with `flexDirection: "row"`, `justifyContent: "center"`, and `flexWrap: "wrap"` to center social login buttons and allow wrapping on smaller screens.

## Styling [#styling]

### Theme Variables Used [#theme-variables-used]

- `theme.spacing(6)` - Gap spacing between child components used by default

## Child Components [#child-components]

- [SignIn.SocialLogins.GoogleLogin](/native-sdk/guide/components/auth/sign-in/social-logins/google-login) - Google authentication button
- [SignIn.SocialLogins.AppleLogin](/native-sdk/guide/components/auth/sign-in/social-logins/apple-login) - Apple authentication button

## Related Components [#related-components]

- [SignIn](/native-sdk/guide/components/auth/sign-in/) - Main sign-in component container
- [SignIn.LoginWithSeparator](/native-sdk/guide/components/auth/sign-in/social-logins/login-with-separator) - Visual separator component
