Core - HostContext.ResolveService

Before using the Core packages, in a specific custom AuthProvider class we had the following logic:

     public override bool IsAuthorized(IAuthSession session, IAuthTokens tokens, Authenticate request = null)
        { 
            using (var authService = HostContext.ResolveService<AuthenticateService>())
            {
                var token = authService.Request.GetAuthenticationToken();
                return AuthenticationToken.IsValid(token);
            }
        }

However the Core package now requires an IRequest to be passed in before resolving the service - but there is nowhere for me to find the current request. I have hunted through so much source code but cannot find how to get this code working again. This is the last thing preventing us moving to netcore.

Any assistance would be appreciated.

You normally can’t get the current request as a singleton and should avoid relying on doing so, it’s an ASP.NET feature that has been disabled by default in .NET Core. Instead you should look at populating anything you need in a custom IAuthSession and retrieve it from that.

This code doesn’t look like you’re using the AuthenticateService at all, you’re just using it as an indirect way of accessing the IRequest. If you register IHttpContextAccessor in your .NET Core Startup class, e.g:

public override void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}

You can access an IRequest instance with HostContext.GetCurrentRequest(), e.g:

var request = HostContext.GetCurrentRequest();
var token = request.GetAuthenticationToken();
return AuthenticationToken.IsValid(token);

But I would still avoid relying on accessing the current request via a singleton.

Yeah this one client does not make use of sessions or the AuthenticateService but uses their own AuthenticationToken mechanism which is a custom stateless cookie. We were just overriding a custom AuthProvider which still allows us to use the [Authenticate] attribute.

What I did so far was to also use IAuthWithRequest:

 public override bool IsAuthorized(IAuthSession session, IAuthTokens tokens, Authenticate request = null)
        {
            return session != null && session.IsAuthenticated;
        }

        public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request)
        {
            var token = ApiAuthTokenProvider.AuthenticationToken.GetToken(request.AccessToken);
            if (AuthenticationToken.IsValid(token))
            {
                session.IsAuthenticated = true;
                session.UserName = token.AppUserId.ToString();
                session.UserAuthId = token.TokenKey.ToString();

                //var response = OnAuthenticated(authService, session, null, null);
                //if (response != null)
                //    return response;

                return new AuthenticateResponse
                {
                    UserId = session.UserAuthId,
                    UserName = session.UserName,
                    SessionId = session.Id,
                };
            }

            throw HttpError.Unauthorized("Invalid login credentials - you will need to login again.");
        }

        public void PreAuthenticate(IRequest req, IResponse res)
        {
            try
            {
                var token = req.GetAuthenticationRawCookie();
                if (!string.IsNullOrWhiteSpace(token))
                {
                    //Need to run SessionFeature filter since its not executed before this attribute (Priority -100)			
                    //SessionFeature.AddSessionIdToRequestFilter(req, res, null); //Required to get req.GetSessionId()

                    using (var authService = HostContext.ResolveService<AuthenticateService>(req))
                    {
                        var response = authService.Post(new Authenticate
                        {
                            provider = Name,
                            AccessToken = token,
                        });
                    }
                }
            }
            catch { }
        }

This seems to have worked, although does not feel super efficient.

Which bit isn’t efficient? If it’s a stateless Cookie there are not going to be any I/O calls.