Skip to content

sapsaldog/supabase-naver-oidc-proxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 

Repository files navigation

supabase-naver-oidc-proxy

A Supabase Edge Function that enables Naver Login with Supabase Custom Provider by proxying Naver's non-standard userinfo API response into standard OIDC format.

Problem

Supabase Custom Provider expects a standard OIDC userinfo response:

{ "sub": "abc123", "email": "user@example.com", "email_verified": true, "name": "John" }

But Naver's userinfo endpoint (https://openapi.naver.com/v1/nid/me) wraps the response in a non-standard envelope:

{
  "resultcode": "00",
  "message": "success",
  "response": {
    "id": "abc123",
    "email": "user@example.com",
    "name": "홍길동",
    "profile_image": "https://..."
  }
}

This causes Supabase Auth to fail with:

Error getting user email from external provider

Solution

Deploy this Edge Function to your Supabase project. It acts as a thin proxy between Supabase Auth and Naver's API — unwrapping the nested response and returning standard OIDC-formatted userinfo.

Client
  └→ supabase.auth.signInWithOAuth({ provider: 'custom:naver' })

Supabase Auth
  ├→ Authorization URL  →  https://nid.naver.com/oauth2/authorize     (direct to Naver)
  ├→ Token URL          →  https://nid.naver.com/oauth2/token         (direct to Naver)
  ├→ JWKS URI           →  https://nid.naver.com/oauth2/jwks          (direct to Naver)
  └→ Userinfo URL       →  https://<project>.supabase.co/functions/v1/naver-userinfo  (this proxy)
                                └→ fetches https://openapi.naver.com/v1/nid/me
                                └→ unwraps { response: { ... } }
                                └→ returns standard OIDC format

Setup

Step 1: Register a Naver Application

  1. Go to Naver Developers and create a new application.
  2. Application name: Your service name
  3. API selection: Select "네이버 로그인 (Naver Login)"
  4. Required consent items (critical):
    • Go to API 권한관리 (API Permission Management)
    • Set 이메일 (Email) to "필수 동의" (Required consent)
    • Without this, Naver will not return the user's email and authentication will fail.
    • Optionally add 이름 (Name), 프로필 사진 (Profile Image), 별명 (Nickname) as needed.
  5. Service environment: Add the environments you need:
    • PC웹 (PC Web):
      • Service URL: Your production domain (e.g., https://myapp.com)
      • Callback URL: https://<your-project-ref>.supabase.co/auth/v1/callback
    • Mobile웹 (Mobile Web) (if applicable):
      • Service URL: Same as above
      • Callback URL: Same as above
  6. Copy your Client ID and Client Secret.

Step 2: Deploy the Edge Function

# Clone this repository
git clone https://github.com/<your-org>/supabase-naver-oidc-proxy.git
cd supabase-naver-oidc-proxy

# Login to Supabase CLI (if not already)
supabase login

# Link to your Supabase project
supabase link --project-ref <your-project-ref>

# Deploy the Edge Function
supabase functions deploy naver-userinfo --no-verify-jwt

Why --no-verify-jwt? This function receives a Naver access token (not a Supabase JWT) in the Authorization header and forwards it to Naver's API. Supabase's built-in JWT verification must be disabled so the Naver token can pass through. Authentication is handled by Naver's own token validation.

After deployment, your function URL will be:

https://<your-project-ref>.supabase.co/functions/v1/naver-userinfo

Step 3: Configure Supabase Custom Provider

Go to Supabase Dashboard → Authentication → Sign In / Providers → Custom Providers → Create Custom Auth Provider:

Field Value
Provider Identifier naver
Display Name Naver (or 네이버)
Configuration Method Manual configuration
Issuer URL https://nid.naver.com
Authorization URL https://nid.naver.com/oauth2/authorize
Token URL https://nid.naver.com/oauth2/token
Userinfo URL https://<your-project-ref>.supabase.co/functions/v1/naver-userinfo
JWKS URI https://nid.naver.com/oauth2/jwks
Client ID (from Step 1)
Client Secret (from Step 1)
Scopes profile
Allow users without email OFF

Important configuration notes:

  • Manual configuration is required. Auto-discovery mode will use Naver's userinfo endpoint directly, bypassing this proxy, and will fail.
  • Scopes must be profile (not openid). Using openid causes Supabase to extract user info from the id_token instead of calling the userinfo endpoint, bypassing this proxy entirely.
  • The Userinfo URL must point to your deployed Edge Function, not to Naver's API directly.

Step 4: Client-side Integration

const { error } = await supabase.auth.signInWithOAuth({
  // Supabase SDK types don't include custom OIDC providers yet.
  // Remove this assertion when @supabase/supabase-js adds custom:* support.
  provider: "custom:naver" as "google",
  options: {
    redirectTo: `${window.location.origin}/auth/callback`,
  },
});

Step 5: Account Linking (Optional)

To allow users who sign in with both Google and Naver (using the same email) to be linked to a single account:

  1. Go to Supabase Dashboard → Authentication → Sign In / Providers
  2. Enable "Allow manual linking"

Field Mapping

Naver API field (response.) OIDC userinfo field Notes
id sub Unique user identifier
email email Requires "필수 동의" in Naver console
(always set to true) email_verified Naver accounts have verified emails
name name Real name
nickname nickname Display name
profile_image picture Avatar URL

Troubleshooting

Error getting user email from external provider

  1. Check Naver API permissions: Ensure email is set to "필수 동의" (required consent) in your Naver app's API Permission Management.
  2. Verify Scopes: Must be profile only. Do NOT include openid — it causes Supabase to skip the userinfo endpoint entirely.
  3. Verify Configuration Method: Must be "Manual configuration", not "Auto-discovery".
  4. Verify Userinfo URL: Must point to your Edge Function (https://<project>.supabase.co/functions/v1/naver-userinfo), not Naver's API.

invalid_scope

Naver does not support email or other non-standard scopes. Use profile only.

Edge Function returns 401

The function was deployed without --no-verify-jwt. Redeploy:

supabase functions deploy naver-userinfo --no-verify-jwt

Edge Function not being called at all

If you see zero invocations in the Edge Functions dashboard after attempting login, the openid scope is likely included. Supabase extracts user info from the id_token when openid is present and never calls the userinfo endpoint. Remove openid from Scopes.

Local Development

supabase start
supabase functions serve naver-userinfo --no-verify-jwt

Test with curl:

curl http://localhost:54321/functions/v1/naver-userinfo \
  -H "Authorization: Bearer <naver-access-token>"

Naver Login Button

When implementing the login button, follow Naver's BI guidelines:

  • Background: #03A94D (Naver green)
  • Logo and text: #FFFFFF (white)
  • Use the N logo icon (do not modify its shape)
  • Recommended button text: "네이버로 계속하기" or "Log in with Naver"

License

MIT

About

Supabase Edge Function proxy for Naver Login — transforms non-standard userinfo response to OIDC format

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors