Skip to content

Commit

Permalink
Add Zendesk to the list of supported providers
Browse files Browse the repository at this point in the history
  • Loading branch information
mozts2005 authored Nov 22, 2024
1 parent ff752ef commit 9fbe030
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public ValueTask HandleAsync(PrepareUserInfoRequestContext context)
// Attach the authorization header containing the access token to the HTTP request.
request.Headers.Authorization = new AuthenticationHeaderValue(Schemes.Bearer, context.Request.AccessToken);

// Remove the access from the request payload to ensure it's not sent twice.
// Remove the access token from the request payload to ensure it's not sent twice.
context.Request.AccessToken = null;

return default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

using System.Collections.Immutable;
using System.Net.Http;
using System.Net.Http.Headers;
using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlerFilters;
using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlers;
using static OpenIddict.Client.WebIntegration.OpenIddictClientWebIntegrationConstants;
Expand All @@ -17,12 +18,102 @@ public static partial class OpenIddictClientWebIntegrationHandlers
public static class Revocation
{
public static ImmutableArray<OpenIddictClientHandlerDescriptor> DefaultHandlers { get; } = ImmutableArray.Create([
/*
* Revocation request preparation:
*/
OverrideHttpMethod.Descriptor,
AttachBearerAccessToken.Descriptor,

/*
* Revocation response extraction:
*/
NormalizeContentType.Descriptor
]);

/// <summary>
/// Contains the logic responsible for overriding the HTTP method for the providers that require it.
/// </summary>
public sealed class OverrideHttpMethod : IOpenIddictClientHandler<PrepareRevocationRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareRevocationRequestContext>()
.AddFilter<RequireHttpUri>()
.UseSingletonHandler<OverrideHttpMethod>()
.SetOrder(PreparePostHttpRequest<PrepareRevocationRequestContext>.Descriptor.Order + 250)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();

/// <inheritdoc/>
public ValueTask HandleAsync(PrepareRevocationRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}

// This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved,
// this may indicate that the request was incorrectly processed by another client stack.
var request = context.Transaction.GetHttpRequestMessage() ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0173));

request.Method = context.Registration.ProviderType switch
{

ProviderTypes.Zendesk => HttpMethod.Delete,

_ => request.Method
};

return default;
}
}

/// <summary>
/// Contains the logic responsible for attaching the token to revoke
/// to the HTTP Authorization header for the providers that require it.
/// </summary>
public sealed class AttachBearerAccessToken : IOpenIddictClientHandler<PrepareRevocationRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareRevocationRequestContext>()
.AddFilter<RequireHttpUri>()
.UseSingletonHandler<AttachBearerAccessToken>()
.SetOrder(AttachHttpParameters<PrepareRevocationRequestContext>.Descriptor.Order - 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();

/// <inheritdoc/>
public ValueTask HandleAsync(PrepareRevocationRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}

// This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved,
// this may indicate that the request was incorrectly processed by another client stack.
var request = context.Transaction.GetHttpRequestMessage() ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0173));

// Zendesk requires using bearer authentication with the token that is going to be revoked.
if (context.Registration.ProviderType is ProviderTypes.Zendesk)
{
request.Headers.Authorization = new AuthenticationHeaderValue(Schemes.Bearer, context.Token);

// Remove the token from the request payload to ensure it's not sent twice.
context.Request.Token = null;
}

return default;
}
}

/// <summary>
/// Contains the logic responsible for normalizing the returned content
/// type of revocation responses for the providers that require it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,9 @@ public ValueTask HandleAsync(ExtractUserInfoResponseContext context)
ProviderTypes.ExactOnline => new(context.Response["d"]?["results"]?[0]?.GetNamedParameters() ??
throw new InvalidOperationException(SR.FormatID0334("d/results/0"))),

// Fitbit and Todoist return a nested "user" object.
ProviderTypes.Fitbit or ProviderTypes.Todoist => new(context.Response["user"]?.GetNamedParameters() ??
// Fitbit, Todoist and Zendesk return a nested "user" object.
ProviderTypes.Fitbit or ProviderTypes.Todoist or ProviderTypes.Zendesk
=> new(context.Response["user"]?.GetNamedParameters() ??
throw new InvalidOperationException(SR.FormatID0334("user"))),

// Harvest returns a nested "user" object and a collection of "accounts".
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2153,6 +2153,35 @@
<Environment Issuer="https://api.login.yahoo.com/" />
</Provider>

<!--
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
██ ▄▄▄ ██ ▄▄▄██ ▀██ ██ ▄▄▀██ ▄▄▄██ ▄▄▄ ██ █▀▄██
██▀▀▀▄▄██ ▄▄▄██ █ █ ██ ██ ██ ▄▄▄██▄▄▄▀▀██ ▄▀███
██ ▀▀▀ ██ ▀▀▀██ ██▄ ██ ▀▀ ██ ▀▀▀██ ▀▀▀ ██ ██ ██
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
-->

<Provider Name="Zendesk" Id="5577b117-1f3d-464f-b987-aabf7c0ab3f7"
Documentation="https://support.zendesk.com/hc/en-us/articles/4408845965210-Using-OAuth-authentication-with-your-application">
<!--
Note: Zendesk is a multitenant provider that relies on subdomains to identify instances.
As such, the following URLs all include a {settings.Tenant} placeholder that will be dynamically
replaced by OpenIddict at runtime by the tenant configured in the Zendesk settings.
-->

<Environment Issuer="https://{settings.Tenant}.zendesk.com/">
<Configuration AuthorizationEndpoint="https://{settings.Tenant}.zendesk.com/oauth/authorizations/new"
TokenEndpoint="https://{settings.Tenant}.zendesk.com/oauth/tokens"
UserInfoEndpoint="https://{settings.Tenant}.zendesk.com/api/v2/users/me"
RevocationEndpoint="https://{settings.Tenant}.zendesk.com/api/v2/oauth/tokens/current.json">
<CodeChallengeMethod Value="S256" />
</Configuration>
</Environment>

<Setting PropertyName="Tenant" ParameterName="tenant" Type="String" Required="true"
Description="Gets or sets the tenant used to identify the Zendesk instance" />
</Provider>

<!--
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
██ ▄▄▄ ██ ▄▄▄ ██ ██ ██ ▄▄▄ ██
Expand Down

0 comments on commit 9fbe030

Please sign in to comment.