Skip to content

Commit

Permalink
use universal Gitea OAuth configuration (#1442)
Browse files Browse the repository at this point in the history
  • Loading branch information
mjcheetham committed Oct 24, 2023
2 parents 2fd111b + 66292a9 commit 6e06153
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 13 deletions.
46 changes: 44 additions & 2 deletions src/shared/Core.Tests/GenericOAuthConfigTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using GitCredentialManager.Tests.Objects;
using Xunit;

Expand All @@ -9,7 +10,9 @@ public class GenericOAuthConfigTests
[Fact]
public void GenericOAuthConfig_TryGet_Valid_ReturnsTrue()
{
var remoteUri = new Uri("https://example.com");
var protocol = "https";
var host = "example.com";
var remoteUri = new Uri($"{protocol}://{host}");
const string expectedClientId = "115845b0-77f8-4c06-a3dc-7d277381fad1";
const string expectedClientSecret = "4D35385D9F24";
const string expectedUserName = "TEST_USER";
Expand Down Expand Up @@ -44,7 +47,12 @@ public void GenericOAuthConfig_TryGet_Valid_ReturnsTrue()
RemoteUri = remoteUri
};

bool result = GenericOAuthConfig.TryGet(trace, settings, remoteUri, out GenericOAuthConfig config);
var input = new InputArguments(new Dictionary<string, string> {
{"protocol", protocol},
{"host", host},
});

bool result = GenericOAuthConfig.TryGet(trace, settings, input, out GenericOAuthConfig config);

Assert.True(result);
Assert.Equal(expectedClientId, config.ClientId);
Expand All @@ -57,5 +65,39 @@ public void GenericOAuthConfig_TryGet_Valid_ReturnsTrue()
Assert.Equal(expectedUserName, config.DefaultUserName);
Assert.True(config.UseAuthHeader);
}

[Fact]
public void GenericOAuthConfig_TryGet_Gitea()
{
var protocol = "https";
var host = "example.com";
var remoteUri = new Uri($"{protocol}://{host}");
const string expectedClientId = GenericOAuthConfig.WellKnown.GiteaClientId;
string[] expectedScopes = Array.Empty<string>();
var expectedRedirectUri = GenericOAuthConfig.WellKnown.LocalIPv4RedirectUri;
var expectedAuthzEndpoint = new Uri(remoteUri, GenericOAuthConfig.WellKnown.GiteaAuthzEndpoint);
var expectedTokenEndpoint = new Uri(remoteUri, GenericOAuthConfig.WellKnown.GiteaTokenEndpoint);

var trace = new NullTrace();
var settings = new TestSettings
{
RemoteUri = remoteUri
};

var input = new InputArguments(new Dictionary<string, string> {
{"protocol", protocol},
{"host", host},
{"wwwauth", "Basic realm=\"Gitea\""}
});

bool result = GenericOAuthConfig.TryGet(trace, settings, input, out GenericOAuthConfig config);

Assert.True(result);
Assert.Equal(expectedClientId, config.ClientId);
Assert.Equal(expectedRedirectUri, config.RedirectUri);
Assert.Equal(expectedScopes, config.Scopes);
Assert.Equal(expectedAuthzEndpoint, config.Endpoints.AuthorizationEndpoint);
Assert.Equal(expectedTokenEndpoint, config.Endpoints.TokenEndpoint);
}
}
}
2 changes: 1 addition & 1 deletion src/shared/Core/GenericHostProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public override async Task<ICredential> GenerateCredentialAsync(InputArguments i
// Cannot check WIA or OAuth support for non-HTTP based protocols
}
// Check for an OAuth configuration for this remote
else if (GenericOAuthConfig.TryGet(Context.Trace, Context.Settings, uri, out GenericOAuthConfig oauthConfig))
else if (GenericOAuthConfig.TryGet(Context.Trace, Context.Settings, input, out GenericOAuthConfig oauthConfig))
{
Context.Trace.WriteLine($"Found generic OAuth configuration for '{uri}':");
Context.Trace.WriteLine($"\tAuthzEndpoint = {oauthConfig.Endpoints.AuthorizationEndpoint}");
Expand Down
53 changes: 43 additions & 10 deletions src/shared/Core/GenericOAuthConfig.cs
Original file line number Diff line number Diff line change
@@ -1,32 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using GitCredentialManager.Authentication.OAuth;

namespace GitCredentialManager
{
public class GenericOAuthConfig
{
public static bool TryGet(ITrace trace, ISettings settings, Uri remoteUri, out GenericOAuthConfig config)
public static bool TryGet(ITrace trace, ISettings settings, InputArguments input, out GenericOAuthConfig config)
{
config = new GenericOAuthConfig();
Uri authzEndpointUri = null;
Uri tokenEndpointUri = null;
var remoteUri = input.GetRemoteUri();

if (!settings.TryGetSetting(
if (input.WwwAuth.Any(x => x.Contains("Basic realm=\"Gitea\"", StringComparison.OrdinalIgnoreCase)))
{
trace.WriteLine($"Using universal Gitea OAuth configuration");
// https://docs.gitea.com/next/development/oauth2-provider?_highlight=oauth#pre-configured-applications
config.ClientId = WellKnown.GiteaClientId;
authzEndpointUri = new Uri(remoteUri, WellKnown.GiteaAuthzEndpoint);
tokenEndpointUri = new Uri(remoteUri, WellKnown.GiteaTokenEndpoint);
config.RedirectUri = WellKnown.LocalIPv4RedirectUri;
}

if (settings.TryGetSetting(
Constants.EnvironmentVariables.OAuthAuthzEndpoint,
Constants.GitConfiguration.Credential.SectionName,
Constants.GitConfiguration.Credential.OAuthAuthzEndpoint,
out string authzEndpoint) ||
!Uri.TryCreate(remoteUri, authzEndpoint, out Uri authzEndpointUri))
out string authzEndpoint))
{
Uri.TryCreate(remoteUri, authzEndpoint, out authzEndpointUri);
}

if (authzEndpointUri == null)
{
trace.WriteLine($"Invalid OAuth configuration - missing/invalid authorize endpoint: {authzEndpoint}");
config = null;
return false;
}

if (!settings.TryGetSetting(
if (settings.TryGetSetting(
Constants.EnvironmentVariables.OAuthTokenEndpoint,
Constants.GitConfiguration.Credential.SectionName,
Constants.GitConfiguration.Credential.OAuthTokenEndpoint,
out string tokenEndpoint) ||
!Uri.TryCreate(remoteUri, tokenEndpoint, out Uri tokenEndpointUri))
out string tokenEndpoint))
{
Uri.TryCreate(remoteUri, tokenEndpoint, out tokenEndpointUri);
}

if (tokenEndpointUri == null)
{
trace.WriteLine($"Invalid OAuth configuration - missing/invalid token endpoint: {tokenEndpoint}");
config = null;
Expand Down Expand Up @@ -74,12 +97,12 @@ public static bool TryGet(ITrace trace, ISettings settings, Uri remoteUri, out G
Constants.EnvironmentVariables.OAuthRedirectUri,
Constants.GitConfiguration.Credential.SectionName,
Constants.GitConfiguration.Credential.OAuthRedirectUri,
out string redirectUrl) &&
Uri.TryCreate(redirectUrl, UriKind.Absolute, out Uri redirectUri))
out string redirectUrl) && Uri.TryCreate(redirectUrl, UriKind.Absolute, out Uri redirectUri))
{
config.RedirectUri = redirectUri;
}
else

if (config.RedirectUri == null)
{
trace.WriteLine($"Invalid OAuth configuration - missing/invalid redirect URI: {redirectUrl}");
config = null;
Expand Down Expand Up @@ -134,5 +157,15 @@ public static bool TryGet(ITrace trace, ISettings settings, Uri remoteUri, out G
public string DefaultUserName { get; set; }

public bool SupportsDeviceCode => Endpoints.DeviceAuthorizationEndpoint != null;

public static class WellKnown
{
// https://docs.gitea.com/next/development/oauth2-provider?_highlight=oauth#pre-configured-applications
public const string GiteaClientId = "e90ee53c-94e2-48ac-9358-a874fb9e0662";
// https://docs.gitea.com/next/development/oauth2-provider?_highlight=oauth#endpoints
public const string GiteaAuthzEndpoint = "/login/oauth/authorize";
public const string GiteaTokenEndpoint = "/login/oauth/access_token";
public static Uri LocalIPv4RedirectUri = new Uri("http://127.0.0.1");
}
}
}

0 comments on commit 6e06153

Please sign in to comment.