From b5566e7ac001cc9f2bac128de0fcb908caf3a5ed Mon Sep 17 00:00:00 2001 From: MiryangJung Date: Tue, 5 Mar 2024 18:05:19 +0900 Subject: [PATCH] feat: add kakao OIDC (#1381) Adds support for OIDC login with Kakao via `signInWithIdToken()`. Fixes: - https://github.com/supabase/gotrue/issues/1358 --- internal/api/provider/kakao.go | 1 + internal/api/provider/oidc.go | 39 ++++++++++++++++++++++++++++++++++ internal/api/token_oidc.go | 6 ++++++ 3 files changed, 46 insertions(+) diff --git a/internal/api/provider/kakao.go b/internal/api/provider/kakao.go index 0963a918c..2482b97a8 100644 --- a/internal/api/provider/kakao.go +++ b/internal/api/provider/kakao.go @@ -12,6 +12,7 @@ import ( const ( defaultKakaoAuthBase = "kauth.kakao.com" defaultKakaoAPIBase = "kapi.kakao.com" + IssuerKakao = "https://kauth.kakao.com" ) type kakaoProvider struct { diff --git a/internal/api/provider/oidc.go b/internal/api/provider/oidc.go index 56949dc3f..01f7ab7e6 100644 --- a/internal/api/provider/oidc.go +++ b/internal/api/provider/oidc.go @@ -59,6 +59,8 @@ func ParseIDToken(ctx context.Context, provider *oidc.Provider, config *oidc.Con token, data, err = parseAppleIDToken(token) case IssuerLinkedin: token, data, err = parseLinkedinIDToken(token) + case IssuerKakao: + token, data, err = parseKakaoIDToken(token) default: if IsAzureIssuer(token.Issuer) { token, data, err = parseAzureIDToken(token) @@ -312,6 +314,43 @@ func parseAzureIDToken(token *oidc.IDToken) (*oidc.IDToken, *UserProvidedData, e return token, &data, nil } +type KakaoIDTokenClaims struct { + jwt.StandardClaims + + Email string `json:"email"` + Nickname string `json:"nickname"` + Picture string `json:"picture"` +} + +func parseKakaoIDToken(token *oidc.IDToken) (*oidc.IDToken, *UserProvidedData, error) { + var claims KakaoIDTokenClaims + + if err := token.Claims(&claims); err != nil { + return nil, nil, err + } + + var data UserProvidedData + + if claims.Email != "" { + data.Emails = append(data.Emails, Email{ + Email: claims.Email, + Verified: true, + Primary: true, + }) + } + + data.Metadata = &Claims{ + Issuer: token.Issuer, + Subject: token.Subject, + Name: claims.Nickname, + PreferredUsername: claims.Nickname, + ProviderId: token.Subject, + Picture: claims.Picture, + } + + return token, &data, nil +} + func parseGenericIDToken(token *oidc.IDToken) (*oidc.IDToken, *UserProvidedData, error) { var data UserProvidedData diff --git a/internal/api/token_oidc.go b/internal/api/token_oidc.go index 5695cb489..58e022afd 100644 --- a/internal/api/token_oidc.go +++ b/internal/api/token_oidc.go @@ -74,6 +74,12 @@ func (p *IdTokenGrantParams) getProvider(ctx context.Context, config *conf.Globa issuer = config.External.Keycloak.URL acceptableClientIDs = append(acceptableClientIDs, config.External.Keycloak.ClientID...) + case p.Provider == "kakao" || p.Issuer == provider.IssuerKakao: + cfg = &config.External.Kakao + providerType = "kakao" + issuer = provider.IssuerKakao + acceptableClientIDs = append(acceptableClientIDs, config.External.Kakao.ClientID...) + default: log.WithField("issuer", p.Issuer).WithField("client_id", p.ClientID).Warn("Use of POST /token with arbitrary issuer and client_id is deprecated for security reasons. Please switch to using the API with provider only!")