Browse Source

Add Trovo to the list of supported providers

pull/1722/head
Kévin Chalet 3 years ago
parent
commit
0ba49f51cf
  1. 96
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs
  2. 18
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs
  3. 45
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs
  4. 31
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml

96
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs

@ -7,8 +7,10 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using OpenIddict.Extensions;
using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpConstants;
using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlerFilters;
using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlers;
using static OpenIddict.Client.SystemNetHttp.OpenIddictClientSystemNetHttpHandlers.Exchange;
@ -25,7 +27,9 @@ public static partial class OpenIddictClientWebIntegrationHandlers
* Token request preparation:
*/
AttachNonStandardBasicAuthenticationCredentials.Descriptor,
AttachNonStandardRequestHeaders.Descriptor,
AttachNonStandardQueryStringParameters.Descriptor,
AttachNonStandardRequestPayload.Descriptor,
/*
* Token response extraction:
@ -99,6 +103,50 @@ public static partial class OpenIddictClientWebIntegrationHandlers
}
}
/// <summary>
/// Contains the logic responsible for attaching additional
/// headers to the request for the providers that require it.
/// </summary>
public sealed class AttachNonStandardRequestHeaders : IOpenIddictClientHandler<PrepareTokenRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareTokenRequestContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachNonStandardRequestHeaders>()
.SetOrder(AttachUserAgentHeader<PrepareTokenRequestContext>.Descriptor.Order + 250)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(PrepareTokenRequestContext 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));
// Trovo requires sending the client identifier in a non-standard "client-id" header and
// the client secret in the payload (formatted using JSON instead of the standard format).
if (context.Registration.ProviderName is Providers.Trovo)
{
request.Headers.Add("Client-ID", context.Request.ClientId);
// Remove the client identifier from the request payload to ensure it's not sent twice.
context.Request.ClientId = null;
}
return default;
}
}
/// <summary>
/// Contains the logic responsible for attaching non-standard query string
/// parameters to the token request for the providers that require it.
@ -147,6 +195,54 @@ public static partial class OpenIddictClientWebIntegrationHandlers
}
}
/// <summary>
/// Contains the logic responsible for attaching a non-standard payload for the providers that require it.
/// </summary>
public sealed class AttachNonStandardRequestPayload : IOpenIddictClientHandler<PrepareTokenRequestContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<PrepareTokenRequestContext>()
.AddFilter<RequireHttpMetadataUri>()
.UseSingletonHandler<AttachNonStandardRequestPayload>()
.SetOrder(AttachFormParameters<PrepareTokenRequestContext>.Descriptor.Order + 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(PrepareTokenRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008));
// 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.Content = context.Registration.ProviderName switch
{
// Trovo returns a 500 internal server error when using the standard
// "application/x-www-form-urlencoded" format and requires using JSON.
Providers.Trovo => JsonContent.Create(context.Transaction.Request,
new MediaTypeHeaderValue(MediaTypes.Json)
{
CharSet = Charsets.Utf8
}),
_ => request.Content
};
return default;
}
}
/// <summary>
/// Contains the logic responsible for attaching non-standard query string
/// parameters to the token request for the providers that require it.

18
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Userinfo.cs

@ -67,12 +67,16 @@ public static partial class OpenIddictClientWebIntegrationHandlers
// (which is statically set to the last version known to be supported by the OpenIddict integration).
if (context.Registration.ProviderName is Providers.Trakt)
{
var options = context.Registration.GetTraktOptions();
request.Headers.Add("trakt-api-key", options.ClientId);
request.Headers.Add("trakt-api-key", context.Registration.ClientId);
request.Headers.Add("trakt-api-version", "2");
}
// Trovo requires sending the client identifier as a separate, non-standard header.
else if (context.Registration.ProviderName is Providers.Trovo)
{
request.Headers.Add("Client-ID", context.Registration.ClientId);
}
return default;
}
}
@ -109,15 +113,21 @@ public static partial class OpenIddictClientWebIntegrationHandlers
// By default, OpenIddict sends the access token as part of the Authorization header
// using the Bearer authentication scheme. Some providers don't support this method
// and require sending the access token as part of the userinfo request payload.
// and require sending the access token as part of the userinfo request payload
// or using a non-standard authentication scheme (e.g OAuth instead of Bearer).
(context.Request.AccessToken, request.Headers.Authorization) = context.Registration.ProviderName switch
{
// These providers require sending the access token as part of the request payload.
Providers.Deezer or
Providers.Mixcloud or
Providers.StackExchange
=> (request.Headers.Authorization?.Parameter, null),
// Trovo requires using the "OAuth" scheme instead of the standard "Bearer" value.
Providers.Trovo
=> (null, new AuthenticationHeaderValue("OAuth", request.Headers.Authorization?.Parameter)),
_ => (context.Request.AccessToken, request.Headers.Authorization)
};

45
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs

@ -22,6 +22,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
* Authentication processing:
*/
HandleNonStandardFrontchannelErrorResponse.Descriptor,
OverrideTokenEndpoint.Descriptor,
AttachNonStandardClientAssertionTokenClaims.Descriptor,
AttachTokenRequestNonStandardClientCredentials.Descriptor,
AdjustRedirectUriInTokenRequest.Descriptor,
@ -125,6 +126,46 @@ public static partial class OpenIddictClientWebIntegrationHandlers
}
}
/// <summary>
/// Contains the logic responsible for overriding the address
/// of the token endpoint for the providers that require it.
/// </summary>
public sealed class OverrideTokenEndpoint : IOpenIddictClientHandler<ProcessAuthenticationContext>
{
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<ProcessAuthenticationContext>()
.UseSingletonHandler<OverrideTokenEndpoint>()
.SetOrder(ResolveTokenEndpoint.Descriptor.Order + 500)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
context.TokenEndpoint = context.Registration.ProviderName switch
{
// Trovo uses a different token endpoint for the refresh token grant.
//
// For more information, see
// https://developer.trovo.live/docs/APIs.html#_4-3-refresh-access-token.
Providers.Trovo when context.GrantType is GrantTypes.RefreshToken
=> new Uri("https://open-api.trovo.live/openplatform/refreshtoken", UriKind.Absolute),
_ => context.TokenEndpoint
};
return default;
}
}
/// <summary>
/// Contains the logic responsible for amending the client
/// assertion methods for the providers that require it.
@ -639,6 +680,10 @@ public static partial class OpenIddictClientWebIntegrationHandlers
// the standard format (that requires using a space as the scope separator):
Providers.Deezer => string.Join(",", context.Scopes),
// The following providers are known to use plus-separated scopes instead of
// the standard format (that requires using a space as the scope separator):
Providers.Trovo => string.Join("+", context.Scopes),
_ => context.Request.Scope
};

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

@ -632,6 +632,37 @@
</Environment>
</Provider>
<!--
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
█▄▄ ▄▄██ ▄▄▀██ ▄▄▄ ██ ███ ██ ▄▄▄ ██
███ ████ ▀▀▄██ ███ ███ █ ███ ███ ██
███ ████ ██ ██ ▀▀▀ ███▄▀▄███ ▀▀▀ ██
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
-->
<Provider Name="Trovo" Documentation="https://developer.trovo.live/docs/APIs.html#_3-authentication">
<Environment Issuer="https://trovo.live/">
<!--
Note: Trovo uses a different token endpoint for the refresh token grant. To accommodate this requirement,
the /exchangetoken endpoint is used as the default value and a dedicated event handler is responsible for
dynamically replacing the token endpoint address to /refreshtoken when using the refresh token grant.
-->
<Configuration AuthorizationEndpoint="https://open.trovo.live/page/login.html"
TokenEndpoint="https://open-api.trovo.live/openplatform/exchangetoken"
UserinfoEndpoint="https://open-api.trovo.live/openplatform/getuserinfo">
<GrantType Value="authorization_code" />
<GrantType Value="refresh_token" />
</Configuration>
<!--
Note: Trovo requires sending the "profile" scope to be able to use the userinfo endpoint.
-->
<Scope Name="user_details_self" Default="true" Required="true" />
</Environment>
</Provider>
<!--
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
█▄▄ ▄▄██ ███ █▄ ▄█▄▄ ▄▄█▄▄ ▄▄██ ▄▄▄██ ▄▄▀██

Loading…
Cancel
Save