Search code examples
c#authenticationbasic-authenticationrestsharp

Since update to RestSharp v110 only 401 unauthorized errors


We used RestSharp v107 without problems this way:

        RestClientOptions options = new RestClientOptions()
        {
            BaseUrl = new Uri(serviceUrl),
            PreAuthenticate = false,
            Timeout = cTimeout,
            UseDefaultCredentials = false,
            UserAgent = $"{Assembly.GetExecutingAssembly().GetName().Name}/{FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion}",
            Encoding = System.Text.Encoding.UTF8
        };
        _restClient = new RestClient(options);

        RestRequest request = new RestRequest("instancetoken", Method.Post);
        request.AddHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        request.AddHeader("Accept", "text/plain");
        request.AddParameter(nameof(username), username);
        request.AddParameter(nameof(password), password);
        RestResponse response = await _restClient.ExecuteAsync(request).ConfigureAwait(true);

Now with v110 we had to change some things and tried it this way:

        RestClientOptions options = new RestClientOptions()
        {
            BaseUrl = new Uri(serviceUrl),
            Authenticator = string.IsNullOrEmpty(instanceToken) ? new HttpBasicAuthenticator(username, password) : (IAuthenticator)new JwtAuthenticator(instanceToken),
            MaxTimeout = cTimeout,
            UseDefaultCredentials = false,
            UserAgent = $"{Assembly.GetExecutingAssembly().GetName().Name}/{FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion}",
            Encoding = System.Text.Encoding.UTF8
        };
        _restClient = new RestClient(options);
        RestRequest request = new RestRequest("instancetoken", Method.Post);
        request.AddHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        request.AddHeader("Accept", "text/plain");
        RestResponse response = await _restClient.ExecuteAsync(request).ConfigureAwait(true);

So now the question: What are we doing wrong here? This way I only get 401 authentication failed errors.


Edit: Sorry forgot to mention one thing. I had used the setter of the instance token to set the authenticator of the jwt if needed. Now it is read only:

    private string _instanceToken = null;
    /// <summary>
    /// Gets or sets the current instance token.
    /// </summary>
    public string InstanceToken
    {
        get => _instanceToken;
        private set
        {
            if (_instanceToken != value)
            {
                _instanceToken = value;
                _restClient.Authenticator = string.IsNullOrEmpty(value) ? null : (IAuthenticator)new JwtAuthenticator(value);
                OnPropertyChanged("InstanceToken");
                OnPropertyChanged("IsConnected");
            }
        }
    }

Solution

  • Based on your comments and updated question, I think this would work. I might still misunderstand the case, but still:

    RestClientOptions options = new RestClientOptions()
    {
        BaseUrl = new Uri(serviceUrl),
        Authenticator = string.IsNullOrEmpty(instanceToken) ? null : new JwtAuthenticator(instanceToken),
        MaxTimeout = cTimeout,
        UserAgent = userAgent,
    };
    _restClient = new RestClient(options);
    var request = new RestRequest("instancetoken", Method.Post);
    if (string.IsNullOrEmpty(instanceToken))
    {
        request
            .AddParameter(nameof(username), username)
            .AddParameter(nameof(password), password);
    }
    var response = await _restClient.ExecuteAsync(request).ConfigureAwait(true);
    

    It won't set the authenticator if there's no token supplied, and add two parameters for the form. I removed the code that sets the Content-Type (POST calls are by default using url-encoded form) and Accept headers as they are set by default anyway.