Question:
I’m experiencing an intermittent issue when using Wix Headless to obtain user refresh and access tokens during login. Sometimes I receive the tokens as expected, but other times the response is either rejected or remains pending. Has anyone else encountered this issue and found a solution?
Product:
Wix Headless (using the Wix SDK with OAuthStrategy)
What are you trying to achieve:
I’m aiming to implement a reliable login flow where, after a successful login, I can retrieve a session token and then obtain the corresponding access and refresh tokens for further authenticated actions. Consistency in receiving these tokens is critical for my application’s functionality.
What have you already tried:
- Implemented the login function using
client.auth.login
to obtain a session token andclient.auth.getMemberTokensForDirectLogin(sessionToken)
to retrieve the tokens. - Reviewed documentation, forum topics, and related articles, but the intermittent nature of the issue (tokens sometimes being returned as a pending promise or resulting in errors) persists.
- I’ve verified that the sessionToken is valid on every request made to
getMemberTokensForDirectLogin(sessionToken)
. Despite the token being valid each time, I still encounter the same issue.
Additional information:
[Include any other pertinent details or information that might be helpful for people to know when trying to answer your question.]
Error Message:
POST https://www.wixapis.com/oauth2/token 400 (Bad Request)
Error logging in: Error: Failed to fetch tokens from OAuth API: . request id: null. Response: {"error":"unknown_error"}
at async getMemberTokens
at async handleLogin
Console Log:
Access and Refresh Tokens: Promise {<pending>}
Relevant Code:
- HOOK :
import { OAuthStrategy, createClient } from "@wix/sdk";
const client = createClient({
modules: {},
auth: OAuthStrategy({
clientId: process.env.NEXT_PUBLIC_WIX_CLIENT_ID!,
}),
});
export let login = async ({ email, password }: { email: string; password: string; }) => {
try {
const response = await client.auth.login({ email, password });
if (response) {
const sessionToken: string = response.data.sessionToken;
console.log("Session Token:", sessionToken);
const tokens = client.auth.getMemberTokensForDirectLogin(sessionToken);
console.log("Access and Refresh Tokens:", tokens);
return tokens;
}
} catch (error) {
console.error("Login API error:", error);
throw error;
}
};
And from the React component:
"use client";
import React, { useState } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { AlertCircle, Loader2, ArrowLeft, Heart } from "lucide-react";
import { login } from "@/lib/createAuthClient";
export default function LoginPage() {
const [email, setEmail] = useState("");
const [sessionToken, setSessionToken] = useState("");
const [password, setPassword] = useState("");
const [message, setMessage] = useState("");
const [isLoading, setIsLoading] = useState(false);
const router = useRouter();
const handleLogin = async (e: React.FormEvent) => {
e.preventDefault();
setIsLoading(true);
setMessage("");
try {
const tokens = await login({ email, password });
console.log("Login successful. Tokens:", tokens);
setMessage("Login successful!");
} catch (error) {
console.error("Error logging in:", error);
setMessage(error.message || "Error logging in. Please try again.");
} finally {
setIsLoading(false);
}
};
}