feat: RapidAPI

This commit is contained in:
Ricardo Carneiro 2026-03-30 11:49:08 -03:00
parent c0b899a148
commit 78bed0fbb1
3 changed files with 29 additions and 2 deletions

View File

@ -100,6 +100,9 @@ namespace QRRapidoApp.Configuration
// OAuth - Microsoft
["microsoft_client_id"] = "Authentication:Microsoft:ClientId",
["microsoft_client_secret"] = "Authentication:Microsoft:ClientSecret",
// RapidAPI
["rapidapi_proxy_secret"] = "RapidApi:ProxySecret",
}
};

View File

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using QRRapidoApp.Models;
using QRRapidoApp.Services;
@ -8,7 +9,9 @@ namespace QRRapidoApp.Filters
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ApiKeyAuthorizeAttribute : Attribute, IAsyncActionFilter
{
private const string ApiKeyHeaderName = "X-API-Key";
private const string ApiKeyHeaderName = "X-API-Key";
private const string RapidApiSecretHeaderName = "X-RapidAPI-Proxy-Secret";
private const string RapidApiUserHeaderName = "X-RapidAPI-User";
// Tracks 429 events per key for abuse logging (key: prefix, value: list of timestamps)
// In-process only; acceptable for the abuse detection use case.
@ -30,10 +33,28 @@ namespace QRRapidoApp.Filters
try
{
// ── RapidAPI flow ────────────────────────────────────────────
var config = context.HttpContext.RequestServices.GetRequiredService<IConfiguration>();
var expectedSecret = config["RapidApi:ProxySecret"];
if (!string.IsNullOrWhiteSpace(expectedSecret) &&
context.HttpContext.Request.Headers.TryGetValue(RapidApiSecretHeaderName, out var incomingSecret) &&
string.Equals(incomingSecret, expectedSecret, StringComparison.Ordinal))
{
var rapidApiUser = context.HttpContext.Request.Headers[RapidApiUserHeaderName].ToString();
context.HttpContext.Items["AuthSource"] = "RapidAPI";
context.HttpContext.Items["RapidApiUser"] = rapidApiUser;
context.HttpContext.Items["ApiPlanTier"] = ApiPlanTier.Pro;
logger.LogInformation("RapidAPI request authorized. RapidAPI-User: {User}", rapidApiUser);
await next();
return;
}
// ── Direct X-API-Key flow ────────────────────────────────────
if (!context.HttpContext.Request.Headers.TryGetValue(ApiKeyHeaderName, out var extractedApiKey))
{
logger.LogWarning("API Key missing in request headers from {IP}", GetIp(context));
context.Result = JsonError(401, "API Key not provided. Use the X-API-Key header.");
context.Result = JsonError(401, "Unauthorized. Provide a valid X-API-Key header or use the RapidAPI marketplace.");
return;
}

View File

@ -188,5 +188,8 @@
"Microsoft.AspNetCore": "Warning"
}
},
"RapidApi": {
"ProxySecret": ""
},
"AllowedHosts": "*"
}