Skip to content

Commit 4153387

Browse files
authored
Add NetSuite to the list of supported providers
1 parent d67512a commit 4153387

File tree

4 files changed

+106
-3
lines changed

4 files changed

+106
-3
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,9 @@ public ValueTask HandleAsync(ExtractTokenResponseContext context)
360360
context.Response.RefreshToken = null;
361361
}
362362

363-
// Note: Alibaba Cloud and Exact Online returns a non-standard "expires_in"
364-
// parameter formatted as a string instead of a numeric type.
365-
if (context.Registration.ProviderType is ProviderTypes.AlibabaCloud or ProviderTypes.ExactOnline &&
363+
// Note: Alibaba Cloud, Exact Online, and NetSuite return a non-standard
364+
// "expires_in" parameter formatted as a string instead of a numeric type.
365+
if (context.Registration.ProviderType is ProviderTypes.AlibabaCloud or ProviderTypes.ExactOnline or ProviderTypes.NetSuite &&
366366
long.TryParse((string?) context.Response[Parameters.ExpiresIn],
367367
NumberStyles.Integer, CultureInfo.InvariantCulture, out long value))
368368
{
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3+
* See https://github.com/openiddict/openiddict-core for more information concerning
4+
* the license and the contributors participating to this project.
5+
*/
6+
7+
using System.Collections.Immutable;
8+
using System.Text.Json;
9+
using OpenIddict.Extensions;
10+
using static OpenIddict.Client.WebIntegration.OpenIddictClientWebIntegrationConstants;
11+
12+
namespace OpenIddict.Client.WebIntegration;
13+
14+
public static partial class OpenIddictClientWebIntegrationHandlers
15+
{
16+
public static class Introspection
17+
{
18+
public static ImmutableArray<OpenIddictClientHandlerDescriptor> DefaultHandlers { get; } =
19+
[
20+
/*
21+
* Introspection response extraction:
22+
*/
23+
MapNonStandardResponseParameters.Descriptor
24+
];
25+
26+
/// <summary>
27+
/// Contains the logic responsible for mapping non-standard response parameters
28+
/// to their standard equivalent for the providers that require it.
29+
/// </summary>
30+
public sealed class MapNonStandardResponseParameters : IOpenIddictClientHandler<ExtractIntrospectionResponseContext>
31+
{
32+
/// <summary>
33+
/// Gets the default descriptor definition assigned to this handler.
34+
/// </summary>
35+
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
36+
= OpenIddictClientHandlerDescriptor.CreateBuilder<ExtractIntrospectionResponseContext>()
37+
.UseSingletonHandler<MapNonStandardResponseParameters>()
38+
.SetOrder(int.MaxValue - 50_000)
39+
.SetType(OpenIddictClientHandlerType.BuiltIn)
40+
.Build();
41+
42+
/// <inheritdoc/>
43+
public ValueTask HandleAsync(ExtractIntrospectionResponseContext context)
44+
{
45+
if (context is null)
46+
{
47+
throw new ArgumentNullException(nameof(context));
48+
}
49+
50+
if (context.Response is null)
51+
{
52+
return default;
53+
}
54+
55+
// Note: NetSuite returns the "scope" parameter as a non-standard JSON array of strings,
56+
// which requires converting it to a space-separated string to ensure the response is
57+
// not rejected by OpenIddict when validating the type of the well-known "scope" claim.
58+
if (context.Registration.ProviderType is ProviderTypes.NetSuite &&
59+
(JsonElement?) context.Response[Parameters.Scope] is { ValueKind: JsonValueKind.Array } element &&
60+
OpenIddictHelpers.ValidateArrayElements(element, JsonValueKind.String))
61+
{
62+
var scopes = new HashSet<string>(StringComparer.Ordinal);
63+
64+
foreach (var item in element.EnumerateArray())
65+
{
66+
var scope = item.GetString()?.ToLowerInvariant();
67+
if (!string.IsNullOrEmpty(scope))
68+
{
69+
scopes.Add(scope);
70+
}
71+
}
72+
73+
context.Response.Scope = string.Join(" ", scopes);
74+
}
75+
76+
return default;
77+
}
78+
}
79+
}
80+
}

src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public static partial class OpenIddictClientWebIntegrationHandlers
6262
.. Device.DefaultHandlers,
6363
.. Discovery.DefaultHandlers,
6464
.. Exchange.DefaultHandlers,
65+
.. Introspection.DefaultHandlers,
6566
.. Protection.DefaultHandlers,
6667
.. Revocation.DefaultHandlers,
6768
.. UserInfo.DefaultHandlers
@@ -826,6 +827,11 @@ public ValueTask HandleAsync(ProcessAuthenticationContext context)
826827
// While PayPal claims the OpenID Connect flavor of the code flow is supported,
827828
// their implementation doesn't return an id_token from the token endpoint.
828829
ProviderTypes.PayPal => (false, false, false),
830+
831+
// NetSuite does not return an id_token when using the refresh_token grant type.
832+
// Additionally, the at_hash inside their id_token is not a valid hash of the
833+
// access token, but is instead a copy of the RS256 signature within the access token.
834+
ProviderTypes.NetSuite => (true, false, false),
829835

830836
_ => (context.ExtractBackchannelIdentityToken,
831837
context.RequireBackchannelIdentityToken,

src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,7 +1584,24 @@
15841584
<Setting PropertyName="ApprovalPrompt" ParameterName="prompt" Type="String" Required="false"
15851585
Description="The value used as the 'approval_prompt' parameter (can be set to 'force' to display the consent form for each authorization demand)" />
15861586
</Provider>
1587+
1588+
<!--
1589+
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
1590+
██ ▀██ ██ ▄▄▄█▄▄ ▄▄██ ▄▄▄ ██ ██ █▄ ▄█▄▄ ▄▄██ ▄▄▄██
1591+
██ █ █ ██ ▄▄▄███ ████▄▄▄▀▀██ ██ ██ ████ ████ ▄▄▄██
1592+
██ ██▄ ██ ▀▀▀███ ████ ▀▀▀ ██▄▀▀▄█▀ ▀███ ████ ▀▀▀██
1593+
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
1594+
-->
1595+
1596+
<Provider Name="NetSuite" Id="df795175-5032-419c-baa9-47c5a325e76e"
1597+
Documentation="https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/chapter_160077062690.html">
1598+
<Environment Issuer="https://system.netsuite.com/"
1599+
ConfigurationEndpoint="https://{settings.AccountId}.suitetalk.api.netsuite.com/.well-known/openid-configuration" />
15871600

1601+
<Setting PropertyName="AccountId" ParameterName="identifier" Type="String" Required="true"
1602+
Description="Your NetSuite account ID (e.g. 123456, or 123456-sb1 for a sandbox)" />
1603+
</Provider>
1604+
15881605
<!--
15891606
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
15901607
██ ▀██ ██ ▄▄▄█▄▀█▀▄█▄▄ ▄▄██ ▄▄▀██ █████ ▄▄▄ ██ ██ ██ ▄▄▀██

0 commit comments

Comments
 (0)