Skip to content

Commit ec53520

Browse files
committed
Fix race condition with supabase auth and init client via Blazor's auth state provider.
1 parent f57d581 commit ec53520

File tree

5 files changed

+75
-77
lines changed

5 files changed

+75
-77
lines changed

Examples/BlazorWebAssemblySupabaseTemplate/Program.cs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,30 +28,34 @@
2828

2929

3030
// ---------- BLAZOR AUTH
31-
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();
31+
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>(
32+
provider => new CustomAuthStateProvider(
33+
provider.GetRequiredService<ILocalStorageService>(),
34+
provider.GetRequiredService<Supabase.Client>()
35+
)
36+
)
37+
;
3238
builder.Services.AddAuthorizationCore();
3339

34-
35-
3640
// ---------- SUPABASE
3741
var url = "https://pylnesfgmytjegzzculn.supabase.co";
3842
var key = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InB5bG5lc2ZnbXl0amVnenpjdWxuIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NjgyOTMwMzcsImV4cCI6MTk4Mzg2OTAzN30.kI29Q_qYWDH5SD6oi5NTwHG6Pxy1e1AUfR8s_ga45lE";
3943

40-
builder.Services.AddScoped<ISupabaseClient<User, Session, Socket, Channel, Bucket, FileObject>>(
41-
provider => new Supabase.Client(
42-
url,
43-
key,
44-
new Supabase.SupabaseOptions
45-
{
46-
AutoRefreshToken = true,
47-
AutoConnectRealtime = true,
48-
PersistSession = true,
49-
SessionHandler = new CustomSupabaseSessionHandler(
50-
provider.GetRequiredService<ILocalStorageService>(),
51-
provider.GetRequiredService<ILogger<CustomSupabaseSessionHandler>>()
52-
)
53-
}
54-
)
44+
builder.Services.AddScoped<Supabase.Client>(
45+
provider => new Supabase.Client(
46+
url,
47+
key,
48+
new Supabase.SupabaseOptions
49+
{
50+
AutoRefreshToken = true,
51+
AutoConnectRealtime = true,
52+
PersistSession = true,
53+
SessionHandler = new CustomSupabaseSessionHandler(
54+
provider.GetRequiredService<ILocalStorageService>(),
55+
provider.GetRequiredService<ILogger<CustomSupabaseSessionHandler>>()
56+
)
57+
}
58+
)
5559
);
5660

5761
// builder.Services.AddScoped<ISupabaseClient<User, Session, Socket, Channel, Bucket, FileObject>>(args => new Supabase.Client(url, key, new Supabase.SupabaseOptions { AutoConnectRealtime = true }));

Examples/BlazorWebAssemblySupabaseTemplate/Providers/CustomAuthStateProvider.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,35 @@ namespace BlazorWebAssemblySupabaseTemplate.Providers;
1111
public class CustomAuthStateProvider : AuthenticationStateProvider
1212
{
1313
private readonly ILocalStorageService _localStorage;
14+
private readonly Supabase.Client _client;
1415
// private readonly IHttpClientFactory httpClientFactory;
1516

1617
// private readonly HttpClient _http;
1718

1819
public CustomAuthStateProvider(
19-
ILocalStorageService localStorage
20+
ILocalStorageService localStorage,
21+
Supabase.Client client
2022
// IHttpClientFactory httpClientFactory
2123
// HttpClient http
2224
)
2325
{
2426
_localStorage = localStorage;
27+
_client = client;
2528
// this.httpClientFactory = httpClientFactory;
2629
// _http = http;
2730
}
2831

2932
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
3033
{
31-
string token = await _localStorage.GetItemAsStringAsync("token");
32-
// string token = "eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTUxMiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiVG9ueSBTdGFyayIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6Iklyb24gTWFuIiwiZXhwIjozMTY4NTQwMDAwfQ.IbVQa1lNYYOzwso69xYfsMOHnQfO3VLvVqV2SOXS7sTtyyZ8DEf5jmmwz2FGLJJvZnQKZuieHnmHkg7CGkDbvA";
33-
34+
// Sets client auth and connects to realtime (if enabled)
35+
await _client.InitializeAsync();
36+
3437
var identity = new ClaimsIdentity();
3538
// _http.DefaultRequestHeaders.Authorization = null;
3639

37-
if (!string.IsNullOrEmpty(token))
40+
if (!string.IsNullOrEmpty(_client.Auth.CurrentSession?.AccessToken))
3841
{
39-
identity = new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt");
42+
identity = new ClaimsIdentity(ParseClaimsFromJwt(_client.Auth.CurrentSession.AccessToken), "jwt");
4043
// _http.DefaultRequestHeaders.Authorization =
4144
// new AuthenticationHeaderValue("Bearer", token.Replace("\"", ""));
4245
}

Examples/BlazorWebAssemblySupabaseTemplate/Providers/CustomSupabaseSessionHandler.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public class CustomSupabaseSessionHandler : ISupabaseSessionHandler
88
{
99
private readonly ILocalStorageService localStorage;
1010
private readonly ILogger<CustomSupabaseSessionHandler> logger;
11+
private static string SESSION_KEY = "SUPABASE_SESSION";
1112

1213
public CustomSupabaseSessionHandler(
1314
ILocalStorageService localStorage,
@@ -22,20 +23,20 @@ ILogger<CustomSupabaseSessionHandler> logger
2223
public async Task<bool> SessionDestroyer()
2324
{
2425
logger.LogInformation("------------------- SessionDestroyer -------------------");
25-
await localStorage.RemoveItemAsync("SUPABASE_SESSION");
26+
await localStorage.RemoveItemAsync(SESSION_KEY);
2627
return true;
2728
}
2829

2930
public async Task<bool> SessionPersistor<TSession>(TSession session) where TSession : Session
3031
{
3132
logger.LogInformation("------------------- SessionPersistor -------------------");
32-
await localStorage.SetItemAsync("SUPABASE_SESSION", session);
33+
await localStorage.SetItemAsync(SESSION_KEY, session);
3334
return true;
3435
}
3536

3637
public async Task<TSession?> SessionRetriever<TSession>() where TSession : Session
3738
{
3839
logger.LogInformation("------------------- SessionRetriever -------------------");
39-
return (TSession?) await localStorage.GetItemAsync<Session>("SUPABASE_SESSION");
40+
return (TSession?) await localStorage.GetItemAsync<Session>(SESSION_KEY);
4041
}
4142
}

Examples/BlazorWebAssemblySupabaseTemplate/Services/AuthService.cs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ namespace BlazorWebAssemblySupabaseTemplate.Services;
1010

1111
public class AuthService
1212
{
13-
private readonly ISupabaseClient<User, Session, Socket, Channel, Bucket, FileObject> client;
13+
private readonly Supabase.Client client;
1414
private readonly AuthenticationStateProvider customAuthStateProvider;
1515
private readonly ILocalStorageService localStorage;
1616
private readonly ILogger<AuthService> logger;
1717

1818
public AuthService(
19-
ISupabaseClient<User, Session, Socket, Channel, Bucket, FileObject> client,
19+
Supabase.Client client,
2020
AuthenticationStateProvider CustomAuthStateProvider,
2121
ILocalStorageService localStorage,
2222
ILogger<AuthService> logger
@@ -28,9 +28,6 @@ ILogger<AuthService> logger
2828
customAuthStateProvider = CustomAuthStateProvider;
2929
this.localStorage = localStorage;
3030
this.logger = logger;
31-
32-
client.InitializeAsync();
33-
client.Auth.RetrieveSessionAsync();
3431
}
3532

3633
public async Task Login(string email, string password)
@@ -42,17 +39,13 @@ public async Task Login(string email, string password)
4239
logger.LogInformation("------------------- User logged in -------------------");
4340
// logger.LogInformation($"instance.Auth.CurrentUser.Id {client?.Auth?.CurrentUser?.Id}");
4441
logger.LogInformation($"client.Auth.CurrentUser.Email {client?.Auth?.CurrentUser?.Email}");
45-
46-
logger.LogInformation($"session?.User?.Id {session?.User?.Id}");
47-
await localStorage.SetItemAsStringAsync("user_id", session?.User?.Id);
4842

49-
await localStorage.SetItemAsStringAsync("token", session?.AccessToken);
5043
await customAuthStateProvider.GetAuthenticationStateAsync();
5144
}
5245

5346
public async Task Logout()
5447
{
55-
await localStorage.RemoveItemAsync("token");
48+
await client.Auth.SignOut();
5649
await customAuthStateProvider.GetAuthenticationStateAsync();
5750
}
5851

Examples/BlazorWebAssemblySupabaseTemplate/Services/DatabaseService.cs

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,45 +11,42 @@ namespace BlazorWebAssemblySupabaseTemplate.Services;
1111

1212
public class DatabaseService
1313
{
14-
private readonly ISupabaseClient<User, Session, Socket, Channel, Bucket, FileObject> client;
15-
private readonly AuthenticationStateProvider customAuthStateProvider;
16-
private readonly ILocalStorageService localStorage;
17-
private readonly ILogger<DatabaseService> logger;
18-
19-
public DatabaseService(
20-
ISupabaseClient<User, Session, Socket, Channel, Bucket, FileObject> client,
21-
AuthenticationStateProvider CustomAuthStateProvider,
22-
ILocalStorageService localStorage,
23-
ILogger<DatabaseService> logger
24-
) : base()
25-
{
26-
logger.LogInformation("------------------- CONSTRUCTOR -------------------");
27-
28-
this.client = client;
29-
customAuthStateProvider = CustomAuthStateProvider;
30-
this.localStorage = localStorage;
31-
this.logger = logger;
32-
33-
client.InitializeAsync();
34-
client.Auth.RetrieveSessionAsync();
35-
}
36-
37-
public async Task<IReadOnlyList<TModel>> From<TModel>() where TModel : BaseModel, new()
38-
{
39-
Postgrest.Responses.ModeledResponse<TModel> modeledResponse = await client.From<TModel>().Get();
40-
return modeledResponse.Models;
41-
}
42-
43-
public async Task<List<TModel>> Delete<TModel>(TModel item) where TModel : BaseModel, new()
44-
{
45-
Postgrest.Responses.ModeledResponse<TModel> modeledResponse = await client.From<TModel>().Delete(item);
46-
return modeledResponse.Models;
47-
}
48-
49-
public async Task<List<TModel>> Insert<TModel>(TModel item) where TModel : BaseModel, new()
50-
{
51-
Postgrest.Responses.ModeledResponse<TModel> modeledResponse = await client.From<TModel>().Insert(item);
52-
return modeledResponse.Models;
53-
}
14+
private readonly Supabase.Client client;
15+
private readonly AuthenticationStateProvider customAuthStateProvider;
16+
private readonly ILocalStorageService localStorage;
17+
private readonly ILogger<DatabaseService> logger;
18+
19+
public DatabaseService(
20+
Supabase.Client client,
21+
AuthenticationStateProvider CustomAuthStateProvider,
22+
ILocalStorageService localStorage,
23+
ILogger<DatabaseService> logger
24+
) : base()
25+
{
26+
logger.LogInformation("------------------- CONSTRUCTOR -------------------");
27+
28+
this.client = client;
29+
customAuthStateProvider = CustomAuthStateProvider;
30+
this.localStorage = localStorage;
31+
this.logger = logger;
32+
}
33+
34+
public async Task<IReadOnlyList<TModel>> From<TModel>() where TModel : BaseModel, new()
35+
{
36+
Postgrest.Responses.ModeledResponse<TModel> modeledResponse = await client.From<TModel>().Get();
37+
return modeledResponse.Models;
38+
}
39+
40+
public async Task<List<TModel>> Delete<TModel>(TModel item) where TModel : BaseModel, new()
41+
{
42+
Postgrest.Responses.ModeledResponse<TModel> modeledResponse = await client.From<TModel>().Delete(item);
43+
return modeledResponse.Models;
44+
}
45+
46+
public async Task<List<TModel>> Insert<TModel>(TModel item) where TModel : BaseModel, new()
47+
{
48+
Postgrest.Responses.ModeledResponse<TModel> modeledResponse = await client.From<TModel>().Insert(item);
49+
return modeledResponse.Models;
50+
}
5451

5552
}

0 commit comments

Comments
 (0)