How to identify the Gateway Lost Authenticate and ReAuthenticate?

I Have a service website named A, and a winform client named B. B called A servicestack service and need Authenticate.
I want the B Client startup to get a Authenticate and only Authenticate once. It works fine.
But when A site restarted, the Authenticate will become invalidate. how to identify the Gateway Lost Authenticate
and ReAuthenticate?
The Code:

  
  public JsonServiceClient GetNewClient()
    {
        var _client = new JsonServiceClient(f.apiurl_weixin);
        _client.Send(new Authenticate
        {
            provider = CredentialsAuthProvider.Name,
            UserName = "username",
            Password = "password",
            RememberMe = true,
        });
        return _client;
    }
var _client = GetNewClient();
container.Register<IServiceGateway>(_client);

Calling Authenticate without any args will return either a populated AuthenticateResponse DTO if authenticated or throw a 401 Unauthorized WebServiceException if not authenticated, e.g:

try
{
    var response = client.Send(new Authenticate());
    //Authenticated
} 
catch (WebServiceException ex)
{
    webEx.StatusCode //= 401
    //Not Authenticated
}

I should note that if you used BasicAuth instead the ServiceClients would automatically behind the scenes process the 401 challenge response and resend the request with BasicAuth populated.

var _client = new JsonServiceClient(f.apiurl_weixin) {
    UserName = "username",
    Password = "password",
};
1 Like

Thanks, you are right. It all works. But when I replace the JsonServiceClient to JsonHttpClient, It will return unauthorized, is any there anything else to set ?

If you replace what code with JsonHttpClient? Can you provide the JsonHttpClient usage which returns the error as well as the server code where you’ve registered the AuthFeature plugin.

I Have a service website named A, and a winform client named B. B called A servicestack service and need Authenticate. in the A has AppHost.cs

public partial class AppHost : AppHostBase
{
     public AppHost()
        : base(g.ApplicationName, typeof(AppHost).Assembly)
    {
        typeof(Authenticate).AddAttributes(new ExcludeAttribute(Feature.Metadata)); 
    }

  
    public override void Configure(Container container)
    {
        //Set MVC to use the same Funq IOC as ServiceStack
        ControllerBuilder.Current.SetControllerFactory(
            new FunqControllerFactory(container));

        SetConfig(new HostConfig
        {
            DebugMode = g.IsDemo, // Show StackTrace in Web Service Exceptions
            EnableFeatures = g.IsDemo ? Feature.All :  Feature.All.Remove(Feature.Metadata), 
            HandlerFactoryPath = "api",
            GlobalResponseHeaders = {  //Support CORS
                    { "Access-Control-Allow-Origin", "*" },
                    { "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" },
                    { "Access-Control-Allow-Headers", "Content-Type" },},
            DefaultContentType = MimeTypes.Json // Default Return Json
        });
        //1. Registering the authorization provider.
        Plugins.Add(new AuthFeature(() => new CustomUserSession(),
          new IAuthProvider[]
          {
              new BasicAuthProvider(),    //Sign-in with Basic Auth
              new CredentialsAuthProvider(),
          })
        {
           
            IncludeRegistrationService = false, 
			MaxLoginAttempts = 5,
            IsValidUsernameFn = delegate (string name)
            {
                if (name.IsNullOrEmpty()) return false;
                return name.Length >= 1 && name.Length <= 32;
            },
        });
}

In the winform client B, In the AppHost, If I used the below code and in othe place used the Gateway , works fine.

public partial class AppHost : AppHostBase
{
    public AppHost()
       : base(g.ApplicationName, typeof(AppHost).Assembly)
    {
    }
    public override void Configure(Container container)
    {
      container.Register<IServiceGateway>(GetNewClient());
    }
   public JsonServiceClient GetNewClient()
    {
        var _client = new JsonServiceClient(f.apiurl_weixin)
        {
            UserName = "username",
            Password = "password"
        };
        return _client;
    }
}

if I replace the JsonServiceClient to JsonHttpClient like below

public partial class AppHost : AppHostBase
{
    public AppHost()
       : base(g.ApplicationName, typeof(AppHost).Assembly)
    {
    }
    public override void Configure(Container container)
    {
      container.Register<IServiceGateway>(GetNewClient());
    }
   public JsonHttpClient GetNewClient()
    {
        var _client = new JsonHttpClient(f.apiurl_weixin)
        {
            UserName = "username",
            Password = "password"
        };
        return _client;
    }
}

when I used the Gateway.Send method to invoke the service from the site A. It will get the error

============================================ 
2016-05-31 19:42:33.0885 【ERROR】【weixin****】 ****.ModifyData Unauthorized ServiceStack.WebServiceException WebServiceException 401 Unauthorized Code: Unauthorized, Message: T GetSyncResponse[T](System.Threading.Tasks.Task`1[T]) 在 ServiceStack.InternalExtensions.GetSyncResponse[T](Task`1 task)
in ServiceStack.JsonHttpClient.Send[TResponse](Object request)
in weixin.****.ModifyData() location C:\****.cs:line 104 
============================================ 

You can specify:

var client = new JsonHttpClient(f.apiurl_weixin) {
    UserName = "username",
    Password = "password",
    AlwaysSendBasicAuthHeader = true
};

Also instead of modifying the global headers to enable CORS Support you should just register the plugin, e.g:

Plugins.Add(new CorsFeature());
1 Like