I was using SS v5.9.0 and update it to the latest version i.e. v6.0.0
After updating I updated the configuration for JWT Token with UseTokenCookie = false
With this configuration my normal default credential auth provider with customerUserSession is working well.
When I hit my APIs with API Key it is failing to authenticate the request whereas it was working with older version.
Here are my auth config.
I used async providers as well i.e CredentialsAuthProviderSync
Plugins.Add(new AuthFeature(() =>
new CustomUserSession(),
new IAuthProvider[]
{
new ApiKeyAuthProvider(AppSettings) {
AllowInHttpParams=true,
Environments=new string[]{"live","dev","test"},
SessionCacheDuration = new TimeSpan(1, 0,0),
RequireSecureConnection = false,
},
new CredentialsAuthProviderSync(AppSettings),
new JwtAuthProvider(AppSettings)
{
AuthKeyBase64 = appConfig.EnvironmentConfig.JwtConfig.JwtAuthKeyBase64,
UseTokenCookie = false,
RequireSecureConnection = false,
EncryptPayload = appConfig.EnvironmentConfig.JwtConfig.EncryptPayload,
ExpireTokensIn=new TimeSpan(1,0, 0),
ExpireRefreshTokensIn = new TimeSpan(1,0, 0),
CreatePayloadFilter = (payload,session) =>
{
payload[Keywords.Session]=session.Id;
},
PopulateSessionFilter = (session, payload, req) =>
{
((CustomUserSession) session).UserSessionId = payload[Keywords.Session];
}
}
}));
Please suggest what changes need to be done to authenticate request with API Key.
Please post the full HTTP Error Response Headers (e.g. using Chrome Web Inspector, Fiddler, WireShark, etc), with any sensitive info scrubbed out (e.g xxxx).
{“responseStatus”:{“errorCode”:“UnauthorizedAccessException”,“message”:“Attempted to perform an unauthorized operation.”,“stackTrace”:“System.UnauthorizedAccessException: Attempted to perform an unauthorized operation.\r\n at AutomotiveLynk.Api.TenantInfoSecurityFilter.<>c.b__0_0(IRequest req, IResponse res, IRequiredRequestInfo dtoInterface) in E:\Alynk\AlynkApi\AutomotiveLynk.Api\Filters\TenantInfoSecurityFilter.cs:line 61\r\n at ServiceStack.Host.TypedFilter1.Invoke(IRequest req, IResponse res, Object dto)\r\n at ServiceStack.ServiceStackHost.ExecTypedFilters(Dictionary2 typedFilters, IRequest req, IResponse res, Object dto)\r\n at ServiceStack.ServiceStackHost.d__425.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at ServiceStack.ServiceStackHost.d__424.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at ServiceStack.Host.RestHandler.d__14.MoveNext()\r\n”,“errors”:[]}}
The exception is coming from within your TenantInfoSecurityFilter:
at AutomotiveLynk.Api.TenantInfoSecurityFilter.<>c.b__0_0(IRequest req, IResponse res, IRequiredRequestInfo dtoInterface)
in E:\Alynk\AlynkApi\AutomotiveLynk.Api\Filters\TenantInfoSecurityFilter.cs:line 61
The same request should have the same behavior, I’d expect something’s different, I’d start with removing all Cookies from Postman.
Can you also try to see if you can call a protected service that authenticates with the Service Clients via any of these supported methods:
var client = new JsonServiceClient(baseUrl) {
Credentials = new NetworkCredential(apiKey, "")
};
var client = new JsonHttpClient(baseUrl) {
BearerToken = apiKey
};
I found that If I decorate my request with [Authenticate] attribute it successfully passes the request.IsAuthenticated() check.
Now in IOC the services whose life cycle is ReusedWithin(ReuseScope.Request) I have custom logic of fetching HostContext.GetCurrentRequest() or base.TryGetCurrentRequest(). This request is not getting authenticated. for the same request.
Eg:
I have service OrderService which in constructor resolve IShipmentProvider and request method is ShipOrder.
Here IShipmentProvider resolved ReusedWithin(ReuseScope.Request) and accept base.TryGetCurrentRequest().
Now calling ShipOrder method getting authenticated successfully with api key but when IOC container goes to resolve the request from base.TryGetCurrentRequest() in IShipmentProvider it throws request.IsAuthenticated() false.
I’d strongly recommend passing in IRequest (base.Request in Services) or the Users Session to any method that needs it, i.e. instead of trying to access it from a singleton request context which is more fragile, fails in bg threads, less testable & host dependent.
In hosts that support it it will return a new IRequest instance it creates Host Request and wont have access anything attached to the IRequest that’s passed through the ServiceStack request pipeline.
As per above eg: My OrderService is driven from ServiceStack.Service but IShipmentProvider is our custom service. How can I access base.Request in my custom service.
The IOC registration is as followed and the request which I get in GetConfig() method is unauthorized and is not containing any session.
container.Register(c => c.Resolve().GetConfig(base.TryGetCurrentRequest())).ReusedWithin(ReuseScope.Request);
Not when registering it in the IOC, when calling it from your Service:
class MyService : Service
{
public IShipmentProvider Dep { get; set; }
public object Any(MyRequest request) => Dep.Method(base.SessionAs<MySession>());
}