Social logins: how do they work?

Facebook, Google, and others allow you to authenticate on different websites through them. How does it work, and what are the risks?

Posted on
5 minutes
1024 words

How does it work?

The underlying protocol that everything relies on is OAuth2. So, let’s start there.

Note: This post was translated from french with the help of AI. The original post was written with the knowledge of a younger me.

OAuth2

If there’s a “2”, that means it’s the second version.

The first version, OAuth, had multiple security vulnerabilities. Never use it.

OAuth2 is the protocol that manages authorization. It allows a device to access resources—data stored on a server.

To do this, it uses scopes. These are parameters that request access to specific resources.

For example, the scope “profile” requests access to the user’s profile information.

The server returns a claim, which represents the requested data.

For the “profile” scope, the claim would be:

{
  "name": "Alice the rabbit",
  "firstname": "Alice",
  "lastname": "the rabbit"
}

This protocol can handle different methods of granting authorization, but for social login, only one concerns us.

Authorization Code Grant

This authentication method allows a service to authorize a user’s login without requiring their password, by trusting an authorization server.

Here’s how it works:

  • The user wants to log in to a service
  • The service redirects the user to the authorization server’s login page
  • The user logs into the authorization server if not already logged in (they enter their password at this step on the authorization server)
  • The authorization server displays a confirmation panel asking the user if they really want to connect to the service
  • The user confirms
  • The server then redirects the user back to the service with an authorization code
  • The service uses the received authorization code to request an access token from the authorization server
  • The authorization server approves the connection between the service and the user
  • The user is logged in to the service

As you can see, the user never enters their password on the service. Password storage happens only on the authorization server.

OpenID Connect

This extension of OAuth2 is managed by the OpenID Foundation, which also maintains the original OpenID with its own mechanism.

This extension handles authentication (identity). It leverages the authorization server as an authentication server.

Building on the “Authorization Code Grant” flow, it verifies the user’s identity with the server using information returned by it (a unique identifier, usually an email, though ideally a UUID).

Additionally, this extension offers several options:

  • The UserInfo endpoint provided by the authentication server: allows dynamic retrieval of user profile information
  • The Session endpoint provided by the authentication server: enables session verification to synchronize sessions (e.g., making sure the user’s session on the service ends when they log out of the server)
  • A logout flow that logs the user out of all services when they log out of the authentication server
  • An implicit login flow called “Single Sign-On” which allows users to log into a service seamlessly. The service and the server appear unified as a single application.

Advantages

This system links multiple services without requiring a password for each one, enhancing security.

It also enables data synchronization between services with a central information silo (a reference point for data storage). This reduces data conflicts when properly implemented.

Risks

Using this system requires full trust in the authorization provider. The provider can access information within connected services because it can impersonate the user and obtain an authorization code on their behalf.

Identity and data synchronization isn’t always well executed. You might end up with multiple accounts on the same service just because you changed your email on the authorization server. The service relying on email won’t recognize the old account and will create a new one.

Logout is often not implemented. Major social login providers use persistent sessions, and many services don’t implement proper logout checks. As a result, services may remain logged in (the user stays connected) even after logging out of Facebook or Google.

If the authorization server is attacked, compromised, or weakened, all linked services become vulnerable.

Attacks

Clickjacking

A hacker could create a malicious service that loads the authorization server inside a transparent iframe.

To simplify, imagine your authentication server as a smartphone.

You tap the center button on your smartphone screen to accept the service.

With clickjacking, the hacker has placed a transparent sheet over your screen, and when you click the button, you’re actually clicking on the sheet, unknowingly granting the malicious service access to your data.

For developers: Implement the X-Frame-Options header with strict settings (e.g., “SameOrigin”) and/or use JavaScript framebusting techniques.

Cross-Site Request Forgery (CSRF)

A hacker can trick the user into clicking an authorization button that redirects, not to the intended service, but to the hacker’s malicious service. The malicious service captures the authorization code and then redirects the user to the correct service.

The user notices nothing, but the malicious service now has the authorization and access tokens.

For developers: Enforce fixed, pre-registered redirect URLs for services.

There are other CSRF variations; I’ll detail them in a future article.

Confused Deputy Problem

This issue occurs when services do not correctly verify the identity of the user utilizing the authorization server.

A malicious user can log in to the authorization server and trick the service into thinking they are another user by manipulating the information used to identify the user.

If the service doesn’t use a reliable identifier for proper user identification, it gets fooled and grants access to the wrong account.

Example:

A service uses an authorization server that provides both a UUID and a username.

The authorization server has two accounts:

  • Alice with UUID: 46d07175-dbf2-46e2-80fc-c6493e481479
  • Oscar with UUID: 362b862b-51b3-41f4-82c7-82eb677a9aa4

The authorization server provides UUIDs as unique identifiers, expecting the service to use them.

But instead, the service chooses to use the username as the unique identifier.

Oscar changes his username to “Alice” (allowed by the server since it uses UUID as the true unique ID).

Now, when Oscar logs into the service, he gains access to Alice’s account (because the service mistakenly uses username as the unique identifier).

For developers: Always choose a truly unique identifier. UUIDs are designed for this purpose. They don’t carry user information and allow users to freely change their details (even email) without affecting uniqueness.