diff --git a/src/Runner.Listener/MessageListener.cs b/src/Runner.Listener/MessageListener.cs index d1e43e283..056fe00f5 100644 --- a/src/Runner.Listener/MessageListener.cs +++ b/src/Runner.Listener/MessageListener.cs @@ -150,6 +150,20 @@ namespace GitHub.Runner.Listener Trace.Error("Catch exception during create session."); Trace.Error(ex); + if (ex is VssOAuthTokenRequestException && creds.Federated is VssOAuthCredential vssOAuthCred) + { + // Check whether we get 401 because the runner registration already removed by the service. + // If the runner registration get deleted, we can't exchange oauth token. + Trace.Error("Test oauth app registration."); + var oauthTokenProvider = new VssOAuthTokenProvider(vssOAuthCred, new Uri(serverUrl)); + var authError = await oauthTokenProvider.ValidateCredentialAsync(token); + if (string.Equals(authError, "invalid_client", StringComparison.OrdinalIgnoreCase)) + { + _term.WriteError("Failed to create a session. The runner registration has been deleted from the server, please re-configure."); + return false; + } + } + if (!IsSessionCreationExceptionRetriable(ex)) { if (_useMigratedCredentials) diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenProvider.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenProvider.cs index e910b259f..84122a494 100644 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenProvider.cs +++ b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenProvider.cs @@ -119,6 +119,15 @@ namespace GitHub.Services.OAuth } } + public async Task ValidateCredentialAsync(CancellationToken cancellationToken) + { + var tokenHttpClient = new VssOAuthTokenHttpClient(this.SignInUrl); + var tokenResponse = await tokenHttpClient.GetTokenAsync(this.Grant, this.ClientCredential, this.TokenParameters, cancellationToken); + + // return the underlying authentication error + return tokenResponse.Error; + } + /// /// Issues a token request to the configured secure token service. On success, the access token issued by the /// token service is returned to the caller @@ -131,7 +140,7 @@ namespace GitHub.Services.OAuth CancellationToken cancellationToken) { if (this.SignInUrl == null || - this.Grant == null || + this.Grant == null || this.ClientCredential == null) { return null;