You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am running the Suno API properly, however i notice every 7 days, i have to update my session id and cookie value.
In the readme it says: "Automatic token maintenance and keep-alive"
How can i make sure my token gets properly refreshed, without me having to manually update this information?
i noticed there was a form of token refresh going on, the main in problem 'in my situation' was that i was running the SunoAPI in a serverless environment, so the refreshed token wasn't persisted.
Since i'm running in Azure and using .NET for my application, i rebuild this Suno API solution into a custom .NET solution, hosted on Azure, with the main difference being that when a unauthorized request happens in the api, i refresh the session_id and cookie and store these in a redis cache. Afterwards the request will be executed again with the refreshed information.
Here is the relevant code, but as i said this is in .NET:
SunoCookieService.cs:publicclassSunoCookieService:BackgroundService{privatereadonlyIHttpClientFactory_clientFactory;privatereadonlyIConfiguration_configuration;privatereadonlyILogger<SunoCookieService>_logger;privatereadonlyIDistributedCache_cache;publicSunoCookieSunoAuth{get;}privateDateTime_tokenExpiryTime;publicSunoCookieService(IHttpClientFactoryclientFactory,IConfigurationconfiguration,ILogger<SunoCookieService>logger,IDistributedCachecache){_clientFactory=clientFactory;_configuration=configuration;_logger=logger;_cache=cache;SunoAuth=newSunoCookie();}protectedoverrideasyncTaskExecuteAsync(CancellationTokenstoppingToken){_logger.LogInformation($"------------------------------------------------------------------");_logger.LogInformation($"ExecuteAsync");awaitInitializeFromCache();while(!stoppingToken.IsCancellationRequested){try{if(DateTime.UtcNow>=_tokenExpiryTime){awaitUpdateTokenAndSession();}else{awaitTouchSession();}}catch(Exceptionex){_logger.LogError(ex,"Error updating token or touching session");}awaitTask.Delay(TimeSpan.FromSeconds(5),stoppingToken);}}privateasyncTaskInitializeFromCache(){_logger.LogInformation($"------------------------------------------------------------------");_logger.LogInformation($"InitializeFromCache");varsessionId=await_cache.GetStringAsync("Suno:SessionId");varcookie=await_cache.GetStringAsync("Suno:Cookie");vartoken=await_cache.GetStringAsync("Suno:Token");vartokenExpiry=await_cache.GetStringAsync("Suno:TokenExpiry");if(string.IsNullOrEmpty(sessionId)||string.IsNullOrEmpty(cookie)){sessionId=_configuration["SunoAPI:SessionId"];cookie=_configuration["SunoAPI:Cookie"];if(string.IsNullOrEmpty(sessionId)||string.IsNullOrEmpty(cookie)){thrownewInvalidOperationException("SessionId and Cookie must be provided either in cache or configuration.");}await_cache.SetStringAsync("Suno:SessionId",sessionId);await_cache.SetStringAsync("Suno:Cookie",cookie);}else{_logger.LogInformation("Initialized from cache");}SunoAuth.SetSessionId(sessionId);SunoAuth.LoadCookie(cookie);if(!string.IsNullOrEmpty(token)){SunoAuth.SetToken(token);if(DateTime.TryParse(tokenExpiry,outvarexpiry)){_tokenExpiryTime=expiry;}_logger.LogInformation($"Initialized with cached token: {token}, expiry time: {_tokenExpiryTime}");}}publicasyncTaskUpdateTokenAndSession(){_logger.LogInformation($"------------------------------------------------------------------");_logger.LogInformation($"UpdateTokenAndSession");varclient=_clientFactory.CreateClient();client.DefaultRequestHeaders.Add("Cookie",SunoAuth.GetCookie());varresponse=awaitclient.PostAsync($"https://clerk.suno.com/v1/client/sessions/{SunoAuth.SessionId}/tokens?_clerk_js_version=4.72.0-snapshot.vc141245",null);if(!response.IsSuccessStatusCode){_logger.LogWarning("Token update failed with status code {StatusCode}. Attempting to refresh session.",response.StatusCode);awaitRefreshSession(client);return;}varsetCookie=response.Headers.GetValues("Set-Cookie").FirstOrDefault();if(!string.IsNullOrEmpty(setCookie)){SunoAuth.LoadCookie(setCookie);await_cache.SetStringAsync("Suno:Cookie",setCookie);}varresponseContent=awaitresponse.Content.ReadAsStringAsync();varjsonResponse=JObject.Parse(responseContent);vartoken=jsonResponse["jwt"]?.ToString();varsessionId=ExtractSessionIdFromToken(token);if(!string.IsNullOrEmpty(token)&&!string.IsNullOrEmpty(sessionId)){SunoAuth.SetToken(token);SunoAuth.SetSessionId(sessionId);await_cache.SetStringAsync("Suno:Token",token);await_cache.SetStringAsync("Suno:SessionId",sessionId);// Set token expiry time assuming token expiry time is 30 minutes from now_tokenExpiryTime=DateTime.UtcNow.AddMinutes(30);// Adjust according to actual token lifetimeawait_cache.SetStringAsync("Suno:TokenExpiry",_tokenExpiryTime.ToString());_logger.LogInformation($"Token updated successfully: {token}, new session ID: {sessionId}, new expiry time: {_tokenExpiryTime}");}}privateasyncTaskTouchSession(){_logger.LogInformation($"------------------------------------------------------------------");_logger.LogInformation($"TouchSession");varclient=_clientFactory.CreateClient();client.DefaultRequestHeaders.Add("Cookie",SunoAuth.GetCookie());varresponse=awaitclient.PostAsync($"https://clerk.suno.com/v1/client/sessions/{SunoAuth.SessionId}/touch?_clerk_js_version=4.72.0-snapshot.vc141245",null);if(!response.IsSuccessStatusCode){_logger.LogWarning("Touch session failed with status code {StatusCode}.",response.StatusCode);return;}varresponseContent=awaitresponse.Content.ReadAsStringAsync();varjsonResponse=JObject.Parse(responseContent);varsession=jsonResponse["response"]?["id"]?.ToString();if(!string.IsNullOrEmpty(session)){_logger.LogInformation($"Session touched successfully: {session}");}}privatestringExtractSessionIdFromToken(stringtoken){_logger.LogInformation($"------------------------------------------------------------------");_logger.LogInformation($"ExtractSessionIdFromToken");if(string.IsNullOrEmpty(token))returnnull;varparts=token.Split('.');if(parts.Length!=3)returnnull;varpayload=parts[1];varjson=Base64UrlDecode(payload);varjwtPayload=JObject.Parse(json);returnjwtPayload["sid"]?.ToString();}privatestaticstringBase64UrlDecode(stringinput){input=input.Replace('-','+').Replace('_','/');switch(input.Length%4){case2:input+="==";break;case3:input+="=";break;}varbytes=Convert.FromBase64String(input);returnEncoding.UTF8.GetString(bytes);}privateasyncTaskRefreshSession(HttpClientclient){_logger.LogInformation($"------------------------------------------------------------------");_logger.LogInformation($"RefreshSession");_logger.LogWarning("Session expired. Attempting to refresh...");varnewSessionId=_configuration["SunoAPI:SessionId"];varnewCookie=_configuration["SunoAPI:Cookie"];SunoAuth.SetSessionId(newSessionId);SunoAuth.LoadCookie(newCookie);await_cache.SetStringAsync("Suno:SessionId",newSessionId);await_cache.SetStringAsync("Suno:Cookie",newCookie);_logger.LogInformation("Session refreshed successfully");awaitUpdateTokenAndSession();// Attempt to update the token again with the new session}}
Activity
FergaliciousPixelicious commentedon Jun 22, 2024
@RaynoldVanHeyningen in case you're interested, check out sumosuno.com
They are able to keep the token alive and it's a plug and play option in case you're interested
RaynoldVanHeyningen commentedon Jun 26, 2024
@FergaliciousPixelicious Thanks, but this is not open-source, it's managed payware, so completely unrelated to this project.
I've built my own solution.
jtoy commentedon Jul 2, 2024
@RaynoldVanHeyningen what is your solution?
RaynoldVanHeyningen commentedon Jul 2, 2024
i noticed there was a form of token refresh going on, the main in problem 'in my situation' was that i was running the SunoAPI in a serverless environment, so the refreshed token wasn't persisted.
Since i'm running in Azure and using .NET for my application, i rebuild this Suno API solution into a custom .NET solution, hosted on Azure, with the main difference being that when a unauthorized request happens in the api, i refresh the session_id and cookie and store these in a redis cache. Afterwards the request will be executed again with the refreshed information.
Here is the relevant code, but as i said this is in .NET: