Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expect XSRF token on validate API key endpoint of the Admin API #1068

Merged
merged 8 commits into from
Mar 5, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
namespace Backbone.AdminApi.Controllers;

[Route("api/v1/ValidateApiKey")]
[Authorize("ApiKey")]
public class ApiKeyValidationController : ControllerBase
{
[HttpPost]
[AllowAnonymous]
[IgnoreAntiforgeryToken]
public IActionResult ValidateApiKey([FromBody] ValidateApiKeyRequest? request, [FromServices] ApiKeyValidator apiKeyValidator)
{
var apiKeyIsValid = apiKeyValidator.IsApiKeyValid(request?.ApiKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,27 @@ class AdminApiClient {

static Future<AdminApiClient> create({required String baseUrl, required String apiKey}) async {
final client = AdminApiClient._(baseUrl, apiKey);
await client._setupXsrf();
await AdminApiClient._setupXsrf(client._dio);
return client;
}

Future<void> _setupXsrf() async {
final xsrf = await _dio.get<String>('/api/v1/xsrf');
static Future<void> _setupXsrf(Dio dio) async {
final xsrf = await dio.get<String>('/api/v1/xsrf');
final xsrfToken = xsrf.data!;
final xsrfCookie = xsrf.headers.value('Set-Cookie');

_dio.options.headers['X-XSRF-TOKEN'] = xsrfToken;
_dio.options.headers['Cookie'] = xsrfCookie;
dio.options.headers['X-XSRF-TOKEN'] = xsrfToken;
dio.options.headers['Cookie'] = xsrfCookie;
}

static Future<bool> validateApiKey({required String baseUrl, required String apiKey}) async {
final isValidResponse = await Dio(
final dio = Dio(
BaseOptions(baseUrl: baseUrl, validateStatus: (status) => status == 200),
).post<Map<String, dynamic>>('/api/v1/validateApiKey', data: {'apiKey': apiKey});
);

await AdminApiClient._setupXsrf(dio);

final isValidResponse = await dio.post<Map<String, dynamic>>('/api/v1/validateApiKey', data: {'apiKey': apiKey});

final isValid = isValidResponse.data!['isValid'] as bool;
return isValid;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public async Task<IEnumerable<Identity>> FindWithTier(TierId tierId, Cancellatio
{
var identities = await (track ? _identitiesDbSet : _readOnlyIdentities)
.IncludeAll(_dbContext)
.AsSplitQuery()
.Where(i => i.TierId == tierId)
.ToListAsync(cancellationToken);

Expand Down
Loading