> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/security/social-authentication.md).

# Social sign-in

Configure Google, Facebook, LinkedIn or Apple as a sign-in provider for users who already exist in OpenIAM, with the real attribute IDs, callback paths and shipped defaults.

## What this is, and when you need it

Social sign-in lets a person authenticate to OpenIAM with an account they already hold at Google, Facebook, LinkedIn or Apple. It finds an **existing** OpenIAM identity and authenticates it with the external account; it creates nothing.

Two nearby things are configured elsewhere and are different mechanisms. [Register users from a social provider](/administration-guide/security/social-registration.md) collects external profile data and feeds it into OpenIAM's self-registration flow. [Just-in-time provisioning](/administration-guide/federation/jit-provisioning.md) creates an identity from a SAML assertion. A provider-reported email address — even one the provider marks verified — is not a globally unique person identifier, not employment proof and not an authorization claim.

## At a glance

|                          |                                                                                                                                                                                                      |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **You will end up with** | A Google button on one test content provider, through which a correlated OpenIAM user signs in, an unmatched Google account is refused, and a `LOGIN_VIA_SOCIAL` audit event records each attempt    |
| **Where**                | **Access Control → Authentication Providers** (`/webconsole/authenticationProviders`), plus a URI pattern for the callback                                                                           |
| **You need first**       | A non-production application in the provider's own developer console, the public HTTPS host users reach OpenIAM on, and the managed system whose principals hold the correlating email address       |
| **Takes**                | Two to three hours, most of it in the provider's console and in the correlation tests                                                                                                                |
| **Reversible**           | Yes for Google, Facebook and LinkedIn — detach the provider and revoke the external client secret. For Apple, deleting the provider **erases its Vault key**, which cannot be recovered from OpenIAM |

## Before you begin

**The redirect URI is not configurable, so confirm the host first.** OpenIAM builds it at request time from the incoming request's own scheme and host, plus a literal path. A reverse proxy that rewrites `Host` or drops `X-Forwarded-Proto` therefore produces a redirect URI the provider will reject. You can read the exact URI OpenIAM sent without any server access: start a sign-in and look at the `redirect_uri` parameter on the authorization URL in the browser's address bar.

{% hint style="warning" %}
**OpenIAM uses the&#x20;*****first*****&#x20;provider of the matching type and ignores the rest.** The callback URL names a social network, not a provider row; OpenIAM looks the type up in its cache and takes the first row it finds. There is no content-provider or tenant selection anywhere in that path. **Keep one active provider per social type**, or you will be debugging why the wrong client ID is used — and the client ID in the provider's own authorization URL is where you will see it. If the chosen provider has no attributes at all, the flow ends with `AUTH_PROVIDER_NOT_FOUND` in the audit event.
{% endhint %}

Decide the correlation rule before you enable anything. The built-in flow passes the provider-reported email into OpenIAM login correlation against the provider's managed system — it does not use the provider's stable subject ID. Treat that as a documented limitation of the shipped path, and plan for its consequences: define uniqueness and case normalisation for email, test a *changed* provider email, never auto-merge two existing people because their emails match, treat the same address asserted by two providers as two claims rather than one person, and deny unknown users unless [social registration](/administration-guide/security/social-registration.md) is deliberately enabled.

## Configure Google sign-in for existing users

{% stepper %}
{% step %}

### Register a non-production Google OAuth client

In the Google Cloud console create an OAuth 2.0 Web application client. Add exactly one authorized redirect URI:

{% code overflow="wrap" %}

```
https://<OPENIAM_HOST>/idp/social/google/callback
```

{% endcode %}

Do **not** add the `selfRegistration` URI — registration is off in this procedure. Request the minimum scopes; `email` is enough to correlate.
{% endstep %}

{% step %}

### Create the provider

**Access Control → Authentication Providers → New** (`/webconsole/newAuthProvider`), type **Google Auth Provider**. Give it a name that includes the environment, and select the managed system whose principals hold the correlating email address.
{% endstep %}

{% step %}

### Fill the attributes

| Field                            | `ATTRIBUTE_NAME`              | Value                                          |
| -------------------------------- | ----------------------------- | ---------------------------------------------- |
| App ID                           | `CLIENT_ID`                   | `<CLIENT_ID>`                                  |
| App Secret                       | `CLIENT_SECRET`               | `<CLIENT_SECRET>`                              |
| Scope                            | `SCOPE`                       | `email`                                        |
| Auth URL                         | `AUTH_URL`                    | `https://accounts.google.com/o/oauth2/v2/auth` |
| Token API path                   | `AUTH_TOKEN_API_CONTEXT_PATH` | `accounts.google.com/o/oauth2/token`           |
| User info path                   | `USER_INFO_CONTEXT_PATH`      | `www.googleapis.com/userinfo/v2/me`            |
| Use google for self registration | `USE_GOOGLE_FOR_REG`          | `false`                                        |

Leave `G_PERSONAL_INFO_PATH` at its default; it is only read on the registration path. Confirm **Auth URL** really is the auth URL and not a scope string — see [Every provider's attributes](#every-providers-attributes-with-shipped-defaults).
{% endstep %}

{% step %}

### Save, then confirm this is the only provider of its type

Filter the provider list on type **Google Auth Provider** and count the rows. There must be exactly one active provider of the type, because the callback takes the first one it finds — more than one and you may be testing the wrong client ID without any error saying so. Delete or repurpose the extras.

{% hint style="warning" %}
**Break-glass, read-only.** The provider list does not show the managed system each provider correlates against, so if you have several and need to tell them apart, read them directly:

{% code overflow="wrap" %}

```sql
SELECT PROVIDER_ID, NAME, MANAGED_SYS_ID FROM AUTH_PROVIDER WHERE PROVIDER_TYPE = 'GOOGLE_AUTH_PROVIDER';
```

{% endcode %}

This is outside the supported change path even though it changes nothing — it bypasses the Webconsole and is not audited as a read. It costs nothing else, and it is the only way to see the correlation target for several providers at once. The supported alternative is to open each provider in turn.
{% endhint %}

Wait out `org.openiam.auth.provider.sweep.time` — `60000` ms — before testing.
{% endstep %}

{% step %}

### Make only the exact callback route reachable unauthenticated

Create a URI pattern for `/idp/social/google/callback` and mark that pattern public. Do **not** make `/idp/social/**` or the application route public. Giving that pattern its own rule stops the content provider's rules applying to it — which for a public callback is fine and is the point.
{% endstep %}

{% step %}

### Attach the provider to one test content provider

`GOOGLE_AUTH_PROVIDER` is one of the three social types that appear in a content provider's **Authentication Provider** drop-down. Use a test content provider, never `DEFAULT_CP`.
{% endstep %}

{% step %}

### Test four identities

| Identity                                                                                                                    | Expected                                                              |
| --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| An active OpenIAM user whose principal on the selected managed system matches the Google email, entitled to the destination | Signs in and reaches the destination                                  |
| An active user matching the email but **not** entitled to the destination resource                                          | Authenticates, then `403`. Authentication is not authorization        |
| A Google account with no matching OpenIAM principal                                                                         | **Denied.** With `USE_GOOGLE_FOR_REG` false there is no creation path |
| A disabled OpenIAM user                                                                                                     | Remains denied                                                        |
| {% endstep %}                                                                                                               |                                                                       |

{% step %}

### Test the failure paths

Deny consent at Google: OpenIAM recognises the provider's `error` parameter and redirects carrying that error rather than failing with a 500, so the expected outcome is an error page and no session. Then replay a used `code`, tamper with `state`, and point the browser at the callback with no parameters. None of these may produce a session.
{% endstep %}
{% endstepper %}

## Verification

| What to check                          | How                                                                                                                                                                                                                                                                                                                                       |
| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Exactly one provider per social type   | Filter the provider list on that type and count. OpenIAM takes the first row it finds                                                                                                                                                                                                                                                     |
| The provider is live in the cache      | 60 s: `org.openiam.auth.provider.sweep.time`                                                                                                                                                                                                                                                                                              |
| The redirect URI matches on both sides | Read the `redirect_uri` parameter off the authorization URL in the browser and compare it with the provider console character for character, including scheme and host                                                                                                                                                                    |
| Attributes persisted                   | Re-open the provider and read the fields back. For the stored values rather than the rendered ones, the read-only break-glass query is `SELECT a.AUTH_ATTRIBUTE_ID, aa.ATTRIBUTE_NAME, a.VALUE FROM AUTH_PROVIDER_ATTRIBUTE a JOIN AUTH_ATTRIBUTE aa ON a.AUTH_ATTRIBUTE_ID = aa.AUTH_ATTRIBUTE_ID WHERE a.PROVIDER_ID = '<PROVIDER_ID>'` |
| Apple key stored                       | The provider was saved first; the Vault key `vault.secret.appleid.private.key.<PROVIDER_ID>` exists                                                                                                                                                                                                                                       |
| Unknown user is denied                 | Sign in with a provider account that has no OpenIAM principal and confirm no identity is created                                                                                                                                                                                                                                          |
| Audit records exist                    | `LOGIN_VIA_SOCIAL` on the callback, naming the authentication provider it resolved to. See [Audit actions and retention](/administration-guide/reference/audit-actions-and-retention.md)                                                                                                                                                  |
| No secret in the audit body            | Inspect one `LOGIN_VIA_SOCIAL` event's recorded request body                                                                                                                                                                                                                                                                              |

{% hint style="warning" %}
**The audit event records the returned social profile.** The flow reads name, nickname, birthday, address, gender, phone number, organization and email from the provider's response, and `LOGIN_VIA_SOCIAL` carries what came back. Open one event and read its recorded body before you widen scope: that tells you exactly what is being retained. Apply your PII access and retention policy to it. Retention is per-action via `org.openiam.audit.log.prune.days.*`, all of which ship `-1`, meaning never prune.
{% endhint %}

## When it goes wrong

| Symptom                                                      | Cause                                                                                                                                    | Fix                                                                                                                                               |
| ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| The social button does not appear                            | The provider is not attached to the content provider, or it is an Apple provider — Apple cannot be attached to a content provider at all | Attach a Google, Facebook or LinkedIn provider                                                                                                    |
| Redirect URI mismatch at the provider                        | OpenIAM sends the request's own scheme and host plus the fixed `/idp/social/<segment>/callback`                                          | Register that exact URL; the proxy's `Host` and `X-Forwarded-Proto` are a deployment matter — [Installation Guide](/installation/installation.md) |
| Sign-in redirects somewhere that is not the provider         | `AUTH_URL` holds the wrong value — a database migrated only part-way through 4.2.0.0 can have the scope string in `Google4`              | Set `AUTH_URL` back to `https://accounts.google.com/o/oauth2/v2/auth`, and finish migrating to the end of 4.2.0.0                                 |
| The wrong client ID is used                                  | Two providers of the same type exist and the cache returned the other one first                                                          | One active provider per social type                                                                                                               |
| `AUTH_PROVIDER_NOT_FOUND` in the audit event                 | No provider of that type exists, or the provider has no attributes at all                                                                | Create the provider and fill every required attribute                                                                                             |
| Google authorization URL is malformed                        | `SCOPE` contains a literal space instead of `+`                                                                                          | The value is interpolated unencoded; use `email+profile`                                                                                          |
| Facebook user-info call fails with an app-secret-proof error | `USE_APP_PROVE` (`FB7`) is off, or the secret is wrong                                                                                   | It ships `true`; leave it on                                                                                                                      |
| Facebook stops working entirely                              | `FB4` and `FB5` pin Graph API `v4.0`                                                                                                     | Update the version in both attributes together                                                                                                    |
| LinkedIn sign-in works but no email arrives                  | `LN8` `LN_EMAIL_PATH` is empty or wrong — LinkedIn needs a second call                                                                   | Set `api.linkedin.com/v2/emailAddress`, or the current equivalent for your LinkedIn product                                                       |
| LinkedIn rejects the scopes                                  | `LN3` ships legacy `r_liteprofile r_emailaddress`; a new LinkedIn app gets OpenID Connect products instead                               | Align `LN3` and `LN6` with the products actually approved on your app                                                                             |
| Apple token exchange fails                                   | The `.p8` key is missing from Vault, or `TEAM_ID` / `KEY_ID` do not match the key                                                        | Confirm `vault.secret.appleid.private.key.<PROVIDER_ID>` exists; re-upload after the first save                                                   |
| Provider authenticates but the user is rejected              | The email does not match a principal on the provider's managed system, or the user is disabled                                           | Fix correlation; do not enable registration as a workaround                                                                                       |
| An unknown user obtained access                              | A registration flag is on — Facebook and LinkedIn ship `true` — or a birthright role is granting on creation                             | Turn the flag off and inspect default roles and business rules                                                                                    |
| Callbacks stop working after moving the IdP context path     | The `/idp` in the social callback paths is fixed, not read from `org.openiam.idp.context.path`                                           | Keep the IdP context path at `/idp`                                                                                                               |

## Roll it back

Detach the provider from the test content provider first and prove local password sign-in still works. Turn any registration flag off before anything else — an active registration path is the part that creates state you cannot un-create. Then revoke the external client secret or Apple key in the provider's console, and remove the public callback URI pattern only once the flow is inactive. Deleting an Apple provider erases its Vault key, so expect no recovery from the OpenIAM side — keep the `.p8` wherever your key custody process keeps it. Retain only redacted audit evidence, under your PII policy.

## The four provider types and their routes

Four of the ten `AUTH_PROVIDER_TYPE` values are the social ones. OpenIAM caches them as one group, so they all refresh on the same provider sweep. Each has one fixed URL segment, and it is not configurable:

| Provider type            | Segment    | Attachable to a content provider   |
| ------------------------ | ---------- | ---------------------------------- |
| `GOOGLE_AUTH_PROVIDER`   | `google`   | Yes                                |
| `FACEBOOK_AUTH_PROVIDER` | `facebook` | Yes                                |
| `LINKEDIN_AUTH_PROVIDER` | `linkedin` | Yes                                |
| `APPLEID_AUTH_PROVIDER`  | `appleid`  | **No** — absent from the drop-down |

Apple is also the only social type that offers a private-key upload, which is how you can tell on screen that you picked it. The list that drop-down is filtered against is built into the product and does **not** come from `AUTH_PROVIDER_TYPE.IS_LINKABLE_TO_CP`; the column and the list disagree about LinkedIn, and the list wins. That disagreement is not visible from the console — the only symptom is a type you can see in the table and not in the drop-down. See [Authentication providers and MFA](/administration-guide/security/authentication-providers-and-mfa.md#the-provider-types-you-can-create).

Three URLs hang off each segment. The callback URL is the one you register at the social provider:

| Purpose             | Concrete path                                                  |
| ------------------- | -------------------------------------------------------------- |
| Start sign-in       | `https://<OPENIAM_HOST>/idp/social/<segment>/login`            |
| Provider callback   | `https://<OPENIAM_HOST>/idp/social/<segment>/callback`         |
| Registration return | `https://<OPENIAM_HOST>/idp/social/<segment>/selfRegistration` |

The `/idp` in those two social paths is **fixed**, not read from `org.openiam.idp.context.path`, so moving the IdP context path breaks social callbacks while leaving everything else working. OpenIAM picks between callback and registration return by looking for `selfRegistration` in the postback URL.

## Every provider's attributes, with shipped defaults

These are `AUTH_ATTRIBUTE` rows. `ATTRIBUTE_NAME` is the name OpenIAM resolves each field by, and the ID is what you would see in `AUTH_PROVIDER_ATTRIBUTE`; the values below are what a fully migrated database ships.

### Google: since 4.2.0.0, corrected twice within that release

| ID        | `ATTRIBUTE_NAME`              | Label                            | Required | Shipped default                                                                                                                         |
| --------- | ----------------------------- | -------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `Google1` | `CLIENT_ID`                   | App ID                           | Y        | —                                                                                                                                       |
| `Google2` | `CLIENT_SECRET`               | App Secret                       | Y        | —                                                                                                                                       |
| `Google3` | `SCOPE`                       | Scope                            | Y        | `email+profile`                                                                                                                         |
| `Google4` | `AUTH_URL`                    | Auth URL                         | Y        | `https://accounts.google.com/o/oauth2/v2/auth`                                                                                          |
| `Google5` | `AUTH_TOKEN_API_CONTEXT_PATH` | Token API path                   | Y        | `accounts.google.com/o/oauth2/token`                                                                                                    |
| `Google6` | `USER_INFO_CONTEXT_PATH`      | User info path                   | Y        | `www.googleapis.com/userinfo/v2/me`                                                                                                     |
| `Google7` | `USE_GOOGLE_FOR_REG`          | Use google for self registration | N        | `false`                                                                                                                                 |
| `Google8` | `G_PERSONAL_INFO_PATH`        | User info path                   | N        | `people.googleapis.com/v1/people/me?personFields=birthdays,names,addresses,genders,nicknames,phoneNumbers,organizations,emailAddresses` |

{% hint style="info" %}
**Google's shipped scope is `+`-joined, not space-joined.** `Google3` ships the literal `email+profile`. That is the URL-encoded form of a space, and it works because OpenIAM puts the value straight into the query string without encoding it again. If you edit the scope, keep the `+` separator — a literal space in that field produces a malformed authorization URL, which you will see immediately in the browser's address bar.

There was a spell within 4.2.0.0 when `AUTH_URL` (`Google4`) was overwritten with the scope string `email profile` instead of the auth URL; a later 4.2.0.0 correction puts the auth URL back and sets `Google3`. A database migrated only part-way through 4.2.0.0 can still be carrying the wrong value. If Google sign-in redirects to something that is not Google, read `AUTH_URL` on the provider first — that is the whole diagnosis.
{% endhint %}

`Google8` is the registration-only path, and it is why Google social registration needs the People API enabled on the Google project; `Google6` alone is enough for plain sign-in. OpenIAM strips spaces out of both values before calling them.

### Facebook: since 4.2.0.0, amended in 4.2.0.5

| ID    | `ATTRIBUTE_NAME`              | Label                              | Required | Shipped default                              |
| ----- | ----------------------------- | ---------------------------------- | -------- | -------------------------------------------- |
| `FB1` | `CLIENT_ID`                   | App ID                             | Y        | —                                            |
| `FB2` | `CLIENT_SECRET`               | App Secret                         | Y        | —                                            |
| `FB3` | `SCOPE`                       | Scope                              | Y        | `email`                                      |
| `FB4` | `AUTH_URL`                    | Auth URL                           | Y        | `https://www.facebook.com/v4.0/dialog/oauth` |
| `FB5` | `AUTH_TOKEN_API_CONTEXT_PATH` | Token API path                     | Y        | `/v4.0/oauth/access_token`                   |
| `FB6` | `USER_INFO_CONTEXT_PATH`      | User info path                     | Y        | `/me`                                        |
| `FB7` | `USE_APP_PROVE`               | App prove?                         | N        | `true`                                       |
| `FB8` | `USE_FACEBOOK_FOR_REG`        | Use facebook for self registration | N        | `true`                                       |

Facebook is the only provider whose `AUTH_TOKEN_API_CONTEXT_PATH` and `USER_INFO_CONTEXT_PATH` are *relative* — they are appended to `org.openiam.ui.api.facebook.baseurl`, which ships as `https://graph.facebook.com`. `FB7` ships `true`, and while it is on OpenIAM derives Facebook's `appsecret_proof` from the client secret and sends it with the user-info call; leave it on. `FB4` and `FB5` pin **Graph API v4.0**, which is well past Facebook's deprecation window — the version string appears in both, so change them together.

### LinkedIn: since 4.2.0.5

| ID    | `ATTRIBUTE_NAME`              | Label                              | Required | Shipped default                                   |
| ----- | ----------------------------- | ---------------------------------- | -------- | ------------------------------------------------- |
| `LN1` | `CLIENT_ID`                   | App ID                             | Y        | —                                                 |
| `LN2` | `CLIENT_SECRET`               | App Secret                         | Y        | —                                                 |
| `LN3` | `SCOPE`                       | Scope                              | Y        | `r_liteprofile r_emailaddress`                    |
| `LN4` | `AUTH_URL`                    | Auth URL                           | Y        | `https://www.linkedin.com/oauth/v2/authorization` |
| `LN5` | `AUTH_TOKEN_API_CONTEXT_PATH` | Token API path                     | Y        | `www.linkedin.com/oauth/v2/accessToken`           |
| `LN6` | `USER_INFO_CONTEXT_PATH`      | User info path                     | Y        | `api.linkedin.com/v2/me`                          |
| `LN7` | `USE_LINKEDIN_FOR_REG`        | Use linkedin for self registration | N        | `true`                                            |
| `LN8` | `LN_EMAIL_PATH`               | Email path                         | Y        | `api.linkedin.com/v2/emailAddress`                |

LinkedIn is the only provider that needs a **second** call to get an email address, and `LN8` is where that path goes. Empty or wrong, sign-in still succeeds and the email arrives blank — so test the email, not just the sign-in. `r_liteprofile` and `r_emailaddress` are legacy scopes; a newly created LinkedIn application is issued the OpenID Connect product instead, so expect to change `LN3` and possibly `LN6`.

### Apple: final state since 4.2.1.1

| ID                        | `ATTRIBUTE_NAME`              | Label           | Required | Shipped default                            |
| ------------------------- | ----------------------------- | --------------- | -------- | ------------------------------------------ |
| `APPLE_ID_CLIENT_ID`      | `CLIENT_ID`                   | App ID          | Y        | —                                          |
| `Apple22`                 | `TEAM_ID`                     | Team ID         | Y        | —                                          |
| `Apple23`                 | `KEY_ID`                      | Key ID          | Y        | —                                          |
| `APPLE_ID_PUBLIC_KEY_URL` | `PUBLIC_KEY_URL`              | Pubic keys path | Y        | `appleid.apple.com/auth/keys`              |
| `Apple24`                 | `AUDIENCE`                    | Audience        | Y        | `https://appleid.apple.com`                |
| `Apple25`                 | `SCOPE`                       | Scope           | Y        | `email`                                    |
| `Apple26`                 | `AUTH_URL`                    | Auth URL        | Y        | `https://appleid.apple.com/auth/authorize` |
| `Apple27`                 | `AUTH_TOKEN_API_CONTEXT_PATH` | Token API path  | Y        | `appleid.apple.com/auth/token`             |

Apple has **no `CLIENT_SECRET` attribute**. The client secret is a JWT OpenIAM signs with the `.p8` private key on every token exchange, which is why `TEAM_ID`, `KEY_ID` and `AUDIENCE` exist and a secret field does not. The label typo *"Pubic keys path"* is shipped and is what you will see on the form.

The private key is not an `AUTH_ATTRIBUTE` either. It goes to Vault, under a key that includes the provider's own ID:

{% code overflow="wrap" %}

```
vault.secret.appleid.private.key.<PROVIDER_ID>
```

{% endcode %}

Because the key name contains the `PROVIDER_ID`, you must create and save the provider **before** uploading the key, and cloning a provider does not clone its key. Deleting the provider erases the key. Whether the secret is present can be confirmed in Vault, not in the Webconsole: the form shows an upload control either way. See [Rotate service credentials](/administration-guide/security/rotate-service-credentials.md) for the key convention.

## API base URLs and the one API key

Nine fixed properties back the calls OpenIAM makes out to each provider:

| Property                                  | Shipped value                |
| ----------------------------------------- | ---------------------------- |
| `org.openiam.ui.api.google.baseurl`       | `https://`                   |
| `org.openiam.ui.api.google.contentType`   | `Json`                       |
| `org.openiam.ui.api.google.apikey`        | *(empty)*                    |
| `org.openiam.ui.api.facebook.baseurl`     | `https://graph.facebook.com` |
| `org.openiam.ui.api.facebook.contentType` | `Json`                       |
| `org.openiam.ui.api.linkedin.baseurl`     | `https://`                   |
| `org.openiam.ui.api.linkedin.contentType` | `Json`                       |
| `org.openiam.ui.api.appleid.baseurl`      | `https://`                   |
| `org.openiam.ui.api.appleid.contentType`  | `Json`                       |

Read `https://` literally: for Google, LinkedIn and Apple the base URL is nothing but a scheme, and the host lives in the provider's own `AUTH_URL` / `AUTH_TOKEN_API_CONTEXT_PATH` / `USER_INFO_CONTEXT_PATH` attributes. That is why those attributes ship with bare hostnames and no scheme. Facebook is the exception and carries a real base URL, which is why its paths are relative.

`org.openiam.ui.api.google.apikey` is the **only** API key property here, it ships empty, and it is **not** used for sign-in at all: it is the Google Translate key, used when `org.openiam.ui.api.translate.provider` is `Google`. So if social sign-in is failing, this is not the cause. Criipto uses the same pair of properties (`org.openiam.ui.api.criipto.baseurl` = `https://`, `...contentType` = `Json`) but is not a social type.

## Related

* [Register users from a social provider](/administration-guide/security/social-registration.md) — the other outcome, configured separately
* [Authentication providers and MFA](/administration-guide/security/authentication-providers-and-mfa.md) — the ten provider types and the capability flags
* [Rotate service credentials](/administration-guide/security/rotate-service-credentials.md) — the `vault.secret.*` key convention

*Applies to OpenIAM 2026.8.1. Last reviewed 7 August 2026.*


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/security/social-authentication.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
