Skip to content

Native App Social Login

Native social login allows mobile app users to sign in using their existing Google, Facebook, or Apple accounts using platform-native SDKs.

Integration Flow

┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Your App │ │ Provider SDK │ │ Horizon API │
└────────┬────────┘ └────────┬─────────┘ └────────┬────────┘
│ │ │
│ 1. User taps │ │
│ "Sign in with X" │ │
│───────────────────────>│ │
│ │ │
│ 2. User authenticates │ │
│<───────────────────────│ │
│ (returns token) │ │
│ │ │
│ 3. appSocialLogin mutation │
│─────────────────────────────────────────────────>│
│ │ │
│ 4. Authentication response │
│ (Horizon token + customer info) │
│<─────────────────────────────────────────────────│

Discovering Available Providers

Query the API to discover which social login providers are enabled:

query GetSocialProviders {
socialLoginProviders {
code
name
colour
iconUrl
clientId
}
}

Example Response:

{
"data": {
"socialLoginProviders": [
{
"code": "google",
"name": "Continue with Google",
"colour": "#4285F4",
"iconUrl": "https://example.com/google-icon.svg",
"clientId": "123456789.apps.googleusercontent.com"
},
{
"code": "facebook",
"name": "Continue with Facebook",
"colour": "#1877F2",
"iconUrl": "https://example.com/facebook-icon.svg",
"clientId": "987654321"
}
]
}
}
FieldUsage
codeUse as providerCode in the login mutation
nameDisplay text for your login button
colourButton background colour (hex)
iconUrlProvider logo for your button
clientIdConfigure your native SDK with this value

Token Types by Platform

ProviderPlatformToken FieldWhat to Send
GoogleiOSaccessTokenOAuth access token
GoogleAndroidauthCodeServer authorization code
FacebookBothaccessTokenOAuth access token
AppleBothaccessTokenIdentity token (JWT)

Google Android Note: The Android SDK returns a server authorization code instead of an access token. Request the server auth code when configuring Google Sign-In and send it as authCode.

Exchanging Token with Horizon

After the user authenticates with the provider SDK, call the appSocialLogin mutation:

mutation AppSocialLogin($input: AppBasedSocialLoginInput!) {
appSocialLogin(input: $input) {
authenticationResponse {
error
token
customer {
id
email
fullName
}
newCustomer
}
form {
title
fields {
name
label
required
type
}
}
socialLoginToken
socialLinkId
socialIdentity {
email
fullName
}
}
}

Input Examples

Google (iOS):

{
"input": {
"providerCode": "google",
"accessToken": "ya29.a0AfH6SMBx..."
}
}

Google (Android):

{
"input": {
"providerCode": "google",
"authCode": "4/P7q7W91a-oMsCeLvIaQm6bTrgtp7..."
}
}

Facebook:

{
"input": {
"providerCode": "facebook",
"accessToken": "EAAGm0PX4ZCps..."
}
}

Apple:

{
"input": {
"providerCode": "apple",
"accessToken": "eyJraWQiOiJXNldjT0..."
}
}

Handling Responses

Success

When error is null, login was successful:

{
"data": {
"appSocialLogin": {
"authenticationResponse": {
"error": null,
"token": "abc123def456...",
"customer": {
"id": "12345",
"email": "user@example.com",
"fullName": "John Doe"
},
"newCustomer": false
}
}
}
}

Store the token securely and use it for authenticated requests. If newCustomer is true, consider showing a welcome flow.

Missing Information (INVALID_DATA)

When the social provider doesn’t supply all required data:

{
"data": {
"appSocialLogin": {
"authenticationResponse": {
"error": "INVALID_DATA"
},
"form": {
"title": "Complete Your Profile",
"fields": [
{ "name": "email", "label": "Email Address", "required": true }
]
},
"socialLoginToken": "temp-token-for-retry...",
"socialIdentity": {
"email": null,
"fullName": "John Doe"
}
}
}
}

Display a form with the fields from form.fields, pre-fill data from socialIdentity, and submit using the socialLogin mutation with missingInformation:

mutation CompleteSocialLogin($input: SocialLoginInput!) {
socialLogin(input: $input) {
authenticationResponse {
error
token
customer { id email }
}
}
}

Variables:

{
"input": {
"socialAuthenticationToken": "temp-token-for-retry...",
"missingInformation": {
"email": "user@example.com"
}
}
}

When an account with the same email already exists:

{
"data": {
"appSocialLogin": {
"authenticationResponse": {
"error": "SOCIAL_LINK_PENDING"
},
"socialLinkId": "link-abc123",
"socialIdentity": {
"email": "existing@example.com"
}
}
}
}

Send a verification email to confirm account ownership:

mutation RequestVerification {
requestSocialLinkVerificationEmail(input: {
socialAuthenticationToken: "the-social-token..."
}) {
error
socialAuthenticationToken
}
}

Error Reference

Error CodeDescriptionResolution
INVALID_DATAMissing required dataDisplay form, collect data, retry
SOCIAL_LINK_PENDINGEmail matches existing accountSend verification email
INVALID_TOKENProvider token is invalidRe-authenticate with provider
EXPIRED_TOKENProvider token has expiredRe-authenticate with provider
ACCOUNT_LOCKEDAccount is lockedDirect user to password reset

Using the Authentication Token

Include the token in subsequent authenticated requests:

fetch('https://api.thehut.net/myprotein/en/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Opaque abc123def456...'
},
body: JSON.stringify({ query, variables })
});

Security Best Practices:

DoDon’t
Store in secure storage (Keychain, EncryptedSharedPreferences)Store in plain text
Clear on logoutLog tokens to console
Transmit only over HTTPSShare tokens between apps

Logged-in users can view and manage connected social accounts:

query {
customer {
socialLinks(status: LINKED) {
socialLinkId
socialLoginProvider { code name }
username
status
}
}
}

Remove a social link:

mutation {
removeSocialLink(input: { socialLinkId: "link-id-123" })
}

FAQ

Why does Google Android use authCode instead of accessToken?

Google’s Android SDK returns a server authorization code that gets exchanged server-side. This provides better security as the access token is never exposed on the device.

What if a provider isn’t in socialLoginProviders?

The provider isn’t enabled for your site. Contact your account manager to enable additional providers.

Can users link multiple social accounts?

Yes. A user can link Google, Facebook, and Apple to the same account and sign in with any of their linked providers.