protected override async Task EnsureAuthenticatedAsync()

in src/JetBrains.Space.Common/RefreshTokenConnection.cs [53:95]


    protected override async Task EnsureAuthenticatedAsync(string? functionName, HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // Authenticate when token expired or when no access token is provided (but refresh token is known)
        if (AuthenticationTokens != null &&
            !string.IsNullOrEmpty(AuthenticationTokens.RefreshToken) && (AuthenticationTokens.HasExpired() || string.IsNullOrEmpty(AuthenticationTokens.AccessToken)))
        {
            // Get new token
            var spaceTokenRequest = new HttpRequestMessage(HttpMethod.Post, ServerUrl + "oauth/token")
                {
                    Headers =
                    {
                        Authorization = AuthenticationHeaderValue.Parse(
                            "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{_clientId}:{_clientSecret}")))
                    },
                    Content = new FormUrlEncodedContent(new []
                    {
                        new KeyValuePair<string?, string?>("grant_type", "refresh_token"),
                        new KeyValuePair<string?, string?>("refresh_token", AuthenticationTokens.RefreshToken),
                        new KeyValuePair<string?, string?>("scope", Scope.ToString())
                    })
                }
                .WithClientAndSdkHeaders(SdkInfo.Version);

            var spaceTokenResponse = await HttpClient.SendAsync(spaceTokenRequest, cancellationToken);
            if (!spaceTokenResponse.IsSuccessStatusCode)
            {
                var exception = await BuildException(functionName, spaceTokenRequest, spaceTokenResponse);
                throw exception;
            }
                
            // Parse new access/refresh token
            using var spaceTokenDocument = await JsonDocument.ParseAsync(await spaceTokenResponse.Content.ReadAsStreamAsync(), cancellationToken: cancellationToken);
            var spaceToken = spaceTokenDocument.RootElement;
                
            AuthenticationTokens = new AuthenticationTokens(
                accessToken: spaceToken.GetStringValue("access_token"),
                refreshToken: spaceToken.GetStringValue("refresh_token") ?? AuthenticationTokens.RefreshToken,
                expires: DateTimeOffset.UtcNow.AddSeconds(spaceToken.GetInt32Value("expires_in"))
            );
        }

        await base.EnsureAuthenticatedAsync(functionName, request, cancellationToken);
    }