Closed nzoschke closed 1 year ago
This is working for me with an echo app like the following:
func main() {
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
supabase := supa.CreateClient(os.Getenv("SUPABASE_PUBLIC_URL"), os.Getenv("SUPABASE_PUBLIC_ANON_KEY"))
e := echo.New()
e.Use(session.Middleware(sessions.NewCookieStore([]byte(os.Getenv("SESSION_SECRET")))))
e.GET("/auth/login/spotify", func(c echo.Context) error {
out, err := supabase.Auth.SignInWithProvider(supa.ProviderSignInOptions{
Provider: "spotify",
RedirectTo: "http://localhost:1323/api/auth/callback",
Scopes: []string{"user-read-email", "user-read-private"},
FlowType: supa.PKCE,
})
if err != nil {
return xerrors.Errorf(": %w", err)
}
// save verifier to session to get back on callback
sess, err := session.Get("session", c)
if err != nil {
return xerrors.Errorf(": %w", err)
}
sess.Values["code_verifier"] = out.CodeVerifier
if err := sess.Save(c.Request(), c.Response()); err != nil {
return xerrors.Errorf(": %w", err)
}
return c.Redirect(http.StatusTemporaryRedirect, out.URL)
})
e.GET("/auth/callback", func(c echo.Context) error {
code := c.Request().URL.Query().Get("code")
if code == "" {
return xerrors.New("missing code")
}
// get verifier from session to exchange with code for token
sess, err := session.Get("session", c)
if err != nil {
return xerrors.Errorf(": %w", err)
}
res, err := supabase.Auth.ExchangeCode(c.Request().Context(), supa.ExchangeCodeOpts{
AuthCode: code,
CodeVerifier: fmt.Sprint(sess.Values["code_verifier"]),
})
if err != nil {
return xerrors.Errorf(": %w", err)
}
return c.JSON(http.StatusOK, res)
})
e.Logger.Fatal(e.Start(":1323"))
}
This returns a token and user like:
{
"access_token": "<REDACTED>",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "<REDACTED>",
"user": {
"id": "<REDACTED>",
"aud": "authenticated",
"role": "authenticated",
"email": "<REDACTED>@example.com",
"invited_at": "0001-01-01T00:00:00Z",
"confirmed_at": "2023-05-13T14:38:47.898965Z",
"confirmation_sent_at": "0001-01-01T00:00:00Z",
"app_metadata": {},
"user_metadata": {
"avatar_url": "https://scontent-atl3-1.xx.fbcdn.net/<REDACTED>",
"email": "<REDACTED>@example.com",
"email_verified": true,
"full_name": "<REDACTED>",
"iss": "https://api.spotify.com/v1",
"name": "<REDACTED>",
"picture": "https://scontent-atl3-1.xx.fbcdn.net/<REDACTED>",
"provider_id": "<REDACTED>",
"sub": "<REDACTED>"
},
"created_at": "2023-05-13T14:38:47.870791Z",
"updated_at": "2023-05-14T01:36:43.057753Z"
}
}
FlowType
option toSignInWithProvider
Implicit
, maintain current behaviorPKCE
, generate a PKCE code and verifier, add PCKE params to authorize URL, and return verifierExchangeCode
function to exchange code and verifier for auth token and userAuthenticatedDetails
Fixes #13