Browse Source

Add Vercel to the list of supported providers

pull/2494/head
Kévin Chalet 4 weeks ago
parent
commit
861c7bc137
  1. 12
      shared/OpenIddict.Extensions/OpenIddictHelpers.cs
  2. 4
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs
  3. 8
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationMarshal.cs
  4. 41
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Discovery.cs
  5. 31
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml

12
shared/OpenIddict.Extensions/OpenIddictHelpers.cs

@ -85,18 +85,6 @@ internal static class OpenIddictHelpers
}
}
/// <summary>
/// Computes an absolute URI from the specified <paramref name="left"/> and <paramref name="right"/> URIs.
/// Note: if the <paramref name="right"/> URI is already absolute, it is directly returned.
/// </summary>
/// <param name="left">The left part.</param>
/// <param name="right">The right part.</param>
/// <returns>An absolute URI from the specified <paramref name="left"/> and <paramref name="right"/>.</returns>
/// <exception cref="InvalidOperationException"><paramref name="left"/> is not an absolute URI.</exception>
[return: NotNullIfNotNull(nameof(right))]
public static Uri? CreateAbsoluteUri(Uri? left, string? right)
=> CreateAbsoluteUri(left, !string.IsNullOrEmpty(right) ? new Uri(right, UriKind.RelativeOrAbsolute) : null);
/// <summary>
/// Computes an absolute URI from the specified <paramref name="left"/> and <paramref name="right"/> URIs.
/// Note: if the <paramref name="right"/> URI is already absolute, it is directly returned.

4
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs

@ -1236,7 +1236,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
// Ensure the authentication demand is tracked by the OpenIddict client system integration
// marshal and resolve the corresponding request forgery protection. If it can't be found,
// this may indicate a session fixation attack: in this case, reject the authentication demand.
if (!_marshal.TryGetRequestForgeryProtection(context.Nonce, out string? protection))
if (!_marshal.TryGetRequestForgeryProtection(context.Nonce, out string? result))
{
context.Reject(
error: Errors.InvalidRequest,
@ -1246,7 +1246,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
return ValueTask.CompletedTask;
}
context.RequestForgeryProtection = protection;
context.RequestForgeryProtection = result;
return ValueTask.CompletedTask;
}

8
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationMarshal.cs

@ -115,19 +115,19 @@ public sealed class OpenIddictClientSystemIntegrationMarshal
/// Tries to resolve the request forgery protection associated with the specified authentication demand.
/// </summary>
/// <param name="nonce">The nonce, used as a unique identifier.</param>
/// <param name="protection">The request forgery protection associated with the specified authentication demand.</param>
/// <param name="result">The request forgery protection associated with the specified authentication demand.</param>
/// <returns><see langword="true"/> if the operation could be validated, <see langword="false"/> otherwise.</returns>
internal bool TryGetRequestForgeryProtection(string nonce, [NotNullWhen(true)] out string? protection)
internal bool TryGetRequestForgeryProtection(string nonce, [NotNullWhen(true)] out string? result)
{
ArgumentException.ThrowIfNullOrEmpty(nonce);
if (_tracker.TryGetValue(nonce, out var operation))
{
protection = operation.Value.RequestForgeryProtection;
result = operation.Value.RequestForgeryProtection;
return true;
}
protection = null;
result = null;
return false;
}

41
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Discovery.cs

@ -21,6 +21,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
*/
AmendIssuer.Descriptor,
AmendGrantTypes.Descriptor,
AmendResponseModes.Descriptor,
AmendCodeChallengeMethods.Descriptor,
AmendScopes.Descriptor,
AmendClientAuthenticationMethods.Descriptor,
@ -157,6 +158,42 @@ public static partial class OpenIddictClientWebIntegrationHandlers
}
}
/// <summary>
/// Contains the logic responsible for amending the supported response modes for the providers that require it.
/// </summary>
public sealed class AmendResponseModes : IOpenIddictClientHandler<HandleConfigurationResponseContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<HandleConfigurationResponseContext>()
.UseSingletonHandler<AmendResponseModes>()
.SetOrder(ExtractGrantTypes.Descriptor.Order + 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
ArgumentNullException.ThrowIfNull(context);
// Note: some providers don't list the response modes they support, which prevents the OpenIddict
// client from using them (unless they are assumed to be enabled by default, like the query or
// fragment response modes). To work around that, the list of supported response modes is amended
// to include the known supported modes for the providers that require it.
// Note: Vercel supports the "query" response mode but exclusively lists
// the "web_message.opener" mode in its server configuration metadata.
if (context.Registration.ProviderType is ProviderTypes.Vercel)
{
context.Configuration.ResponseModesSupported.Add(ResponseModes.Query);
}
return ValueTask.CompletedTask;
}
}
/// <summary>
/// Contains the logic responsible for amending the supported
/// code challenge methods for the providers that require it.
@ -169,7 +206,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<HandleConfigurationResponseContext>()
.UseSingletonHandler<AmendCodeChallengeMethods>()
.SetOrder(ExtractCodeChallengeMethods.Descriptor.Order + 500)
.SetOrder(AmendResponseModes.Descriptor.Order + 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
@ -395,7 +432,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
else if (context.Registration.ProviderType is ProviderTypes.Auth0)
{
context.Configuration.EndSessionEndpoint ??= OpenIddictHelpers.CreateAbsoluteUri(
context.Registration.Issuer, "oidc/logout");
context.Registration.Issuer, new Uri("oidc/logout", UriKind.Relative));
}
// While Huawei supports OpenID Connect discovery, the configuration

31
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml

@ -798,9 +798,9 @@
<Provider Name="ExactOnline" DisplayName="Exact Online" Id="7fbc91df-e1c0-4f7e-9c65-f86b1d173ab9"
Documentation="https://support.exactonline.com/community/s/knowledge-base#All-All-DNO-Content-oauth-eol-oauth-dev-impleovervw">
<Environment Issuer="{settings.Issuer}">
<Configuration AuthorizationEndpoint="{CreateAbsoluteUri(settings.Issuer, 'api/oauth2/auth')}"
TokenEndpoint="{CreateAbsoluteUri(settings.Issuer, 'api/oauth2/token')}"
UserInfoEndpoint="{CreateAbsoluteUri(settings.Issuer, 'api/v1/current/Me')}">
<Configuration AuthorizationEndpoint="{CreateAbsoluteUri(settings.Issuer, new Uri('api/oauth2/auth', UriKind.Relative))}"
TokenEndpoint="{CreateAbsoluteUri(settings.Issuer, new Uri('api/oauth2/token', UriKind.Relative))}"
UserInfoEndpoint="{CreateAbsoluteUri(settings.Issuer, new Uri('api/v1/current/Me', UriKind.Relative))}">
<GrantType Value="authorization_code" />
<GrantType Value="refresh_token" />
</Configuration>
@ -1517,9 +1517,9 @@
-->
<Environment Issuer="{settings.Issuer}">
<Configuration AuthorizationEndpoint="{CreateAbsoluteUri(settings.Issuer, 'oauth/authorize')}"
TokenEndpoint="{CreateAbsoluteUri(settings.Issuer, 'oauth/token')}"
UserInfoEndpoint="{CreateAbsoluteUri(settings.Issuer, 'api/v1/accounts/verify_credentials')}">
<Configuration AuthorizationEndpoint="{CreateAbsoluteUri(settings.Issuer, new Uri('oauth/authorize', UriKind.Relative))}"
TokenEndpoint="{CreateAbsoluteUri(settings.Issuer, new Uri('oauth/token', UriKind.Relative))}"
UserInfoEndpoint="{CreateAbsoluteUri(settings.Issuer, new Uri('api/v1/accounts/verify_credentials', UriKind.Relative))}">
<GrantType Value="authorization_code" />
<GrantType Value="client_credentials" />
<GrantType Value="password" />
@ -1696,9 +1696,9 @@
<Provider Name="Nextcloud" Id="f256847d-c720-4b2f-bda0-69e8f4bceac2"
Documentation="https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/oauth2.html">
<Environment Issuer="{settings.Issuer}">
<Configuration AuthorizationEndpoint="{CreateAbsoluteUri(settings.Issuer, 'index.php/apps/oauth2/authorize')}"
TokenEndpoint="{CreateAbsoluteUri(settings.Issuer, 'index.php/apps/oauth2/api/v1/token')}"
UserInfoEndpoint="{CreateAbsoluteUri(settings.Issuer, 'ocs/v2.php/cloud/user?format=json')}">
<Configuration AuthorizationEndpoint="{CreateAbsoluteUri(settings.Issuer, new Uri('index.php/apps/oauth2/authorize', UriKind.Relative))}"
TokenEndpoint="{CreateAbsoluteUri(settings.Issuer, new Uri('index.php/apps/oauth2/api/v1/token', UriKind.Relative))}"
UserInfoEndpoint="{CreateAbsoluteUri(settings.Issuer, new Uri('ocs/v2.php/cloud/user?format=json', UriKind.Relative))}">
<GrantType Value="authorization_code" />
<GrantType Value="refresh_token" />
</Configuration>
@ -2538,6 +2538,19 @@
</Environment>
</Provider>
<!--
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
██ ███ ██ ▄▄▄██ ▄▄▀██ ▄▄▀██ ▄▄▄██ █████
███ █ ███ ▄▄▄██ ▀▀▄██ █████ ▄▄▄██ █████
███▄▀▄███ ▀▀▀██ ██ ██ ▀▀▄██ ▀▀▀██ ▀▀ ██
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
-->
<Provider Name="Vercel" Id="f44fc1d8-8575-4271-aae5-3e6bdc030d46"
Documentation="https://vercel.com/docs/sign-in-with-vercel/getting-started">
<Environment Issuer="https://vercel.com/" />
</Provider>
<!--
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
██ ███ █ ▄▄▄██ ▄▄▀█▄ ▄██ ▄▀▄ █▄ ▄██

Loading…
Cancel
Save