본문 바로가기
개발 (ENG)

Server-Side Design for Social Login (Pre-Implementation Architecture)

by 새싹 아빠 2026. 1. 23.

I have been thinking about how to design the server when implementing social login. I want to implement automatic login properly, but there are many different cases to consider: existing users, new users who want to sign up, users who have agreed to the terms, and so on. It is not as simple as it first seems. I am writing this post hoping that developers who are facing similar 고민 will read it and leave feedback.

 

In this article, I will organize the server-side design of “Social Login + Terms Agreement + JWT + RefreshToken” from a design perspective, without focusing on code.

 

The key questions I want to share in this article are:

  • What is the difference between Firebase authentication and server-side login (JWT)?
  • Should sign-up and sign-in APIs be separated?
  • Up to what point should we consider “sign-up completed” when terms agreement is involved?
  • When is the best time to issue and store a RefreshToken for clean automatic login?

 

1. One-Sentence Conclusion

Separate external authentication (Firebase) from internal authentication (JWT), treat terms agreement as the condition for completing sign-up, and issue RefreshTokens only to users who have completed sign-up to enable automatic login.

 

2. Separating External Authentication and Internal Authentication

The biggest reason server design becomes confusing is thinking “social login success = login completed.” In practice, these two concepts should be clearly separated.

Role of External Authentication (Firebase / Social Login)

  • Proves who the user is.
  • Verifies that the social account is real and not forged.
  • From the server’s perspective, it is only a “means of identity verification,” not a completed service login.

Role of Internal Authentication (Our Server)

  • Determines how the user should be treated within our service.
  • Is responsible for user creation/retrieval, terms agreement status, token issuance, and automatic login decisions.
  • The final authority on login status always belongs to the server.

 

3. User State Model from the Server’s Perspective (3 Stages)

The server does not make a user a “full member” in a single step. Especially when a terms agreement screen exists, managing user state step by step makes the design much clearer.

Stage 1: External Authentication Completed

  • The client successfully authenticates via Firebase.
  • The user is not yet confirmed as a service user.

Stage 2: Internal User Creation (Temporary User)

  • The server creates a user record or retrieves an existing one.
  • The user remains in a “terms not agreed” state (e.g., isTermsAgreed = false).
  • An AccessToken can be issued, but sign-up is not yet completed.

Stage 3: Sign-Up Completed

  • Terms agreement is completed and isTermsAgreed = true.
  • From this point, a RefreshToken is issued and stored.
  • The user becomes eligible for automatic login.

 

4. Should sign-up and sign-in APIs be separated?

In conclusion, for social login, it is not necessary to strictly separate sign-up and sign-in APIs. Instead, it is common in practice to branch between “new user” and “existing user” inside the server logic.

A social login API typically performs the following tasks:

  • Verify the Firebase token (external authentication).
  • Look up the user in the database by (firebaseUid, provider) or email.
  • Create a new user if none exists (possibly as a temporary user).
  • Issue an AccessToken.
  • Include the terms agreement status (isTermsAgreed) in the response.

In other words, unifying everything under a single “social login” endpoint and letting the response determine the next screen (terms or main) results in a clean and simple structure.

 

5. Terms Agreement Is Not Just UI, but a “Sign-Up Completion Trigger”

If a terms agreement screen exists, agreeing to the terms is not just a UI step, but a server-side condition for “sign-up completion.”

Therefore, user states are clearly divided as follows:

  • Terms not agreed: only an AccessToken exists (temporary authentication), no RefreshToken, automatic login not allowed.
  • Terms agreed: RefreshToken issued and stored, automatic login allowed.

 

6. When Should a RefreshToken Be Issued and Stored?

The conclusion we reached is simple.

Issuing and storing the RefreshToken at the moment when terms agreement is completed is the safest and cleanest approach.

The reasons are:

  • A RefreshToken represents “long-term login (automatic login) permission.”
  • A user who has not agreed to the terms has not fully completed sign-up.
  • After sign-up is completed, the automatic login policy becomes clear and consistent.

 

7. Automatic Login Decision Logic (Server Perspective)

Automatic login should not be determined solely by the client checking “whether a token exists.” The final decision must be made by the server.

From the server’s perspective, automatic login is allowed only when all of the following conditions are met:

  • A RefreshToken exists.
  • The RefreshToken is valid (not expired, revoked, or mismatched).
  • The user’s state indicates sign-up completion (e.g., isTermsAgreed = true).

Only when all three conditions are true does the server issue a new AccessToken and allow automatic login.

 

8. Summary of the Entire Flow

  • The client performs external authentication via Firebase.
  • The server retrieves or creates the user and checks the terms agreement status.
  • Before terms agreement, the user is treated as temporary and proceeds with AccessToken-based authentication only.
  • Once terms agreement is completed, the server marks sign-up as completed.
  • A RefreshToken is issued and stored only for users who have completed sign-up.
  • Automatic login is allowed while the RefreshToken remains valid.

 

9. Final Thoughts

  • Social login success does not mean sign-up is completed.
  • Treating terms agreement as the server-side sign-up completion trigger makes the design clear.
  • Since a RefreshToken represents “automatic login permission,” it should be issued only to users who have completed sign-up.
  • The final authority for automatic login decisions should always reside on the server.

This is the best structure I could come up with at my current level. If you know of better approaches, I would really appreciate it if you could share your thoughts in the comments.

Thank you.