Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
58bb3ee
feat: add Etsy OAuth provider
DevTKSS Nov 3, 2025
22129b6
docs(EtsyProvider): Add Provider usage guide with samples and specifi…
DevTKSS Nov 3, 2025
e291fb3
test: add tests for Etsy OAuth provider
DevTKSS Nov 3, 2025
ae0b1d6
chore: Compare and align to other existing Providers
DevTKSS Nov 6, 2025
47bdf17
chore: update const string to static readonly string
DevTKSS Nov 7, 2025
b60d67d
test(EtsyProvider): Added unit tests for EtsyAuthenticationOptions an…
DevTKSS Nov 6, 2025
ff08b69
chore: updated and documented test data in `bundle.json`
DevTKSS Nov 6, 2025
84aab36
chore: Rename Public to Personal Access Type, to match the Etsy Api n…
DevTKSS Nov 6, 2025
49c8764
chore(EtsyAccessTypes): Remove commented member and test/-cases that …
DevTKSS Nov 7, 2025
056ca64
chore(EtsyProvider): tfm version bump
DevTKSS Nov 7, 2025
8a03cf3
chore: Add DetailedUserInfoClaimMappings and add xml docs
DevTKSS Nov 7, 2025
a37be50
chore(Etsy): align oauth scopes with the docs table
DevTKSS Nov 7, 2025
dc74ed2
chore(EtsyAuthenticationHandler): rename variables and formating appl…
DevTKSS Nov 7, 2025
4da0bed
chore(EtsyPostConfigureOptions): add DetailedUserInfo Config via Post…
DevTKSS Nov 7, 2025
cb671c7
chore: Update xml docs and refactor to Property pattern with declarat…
DevTKSS Nov 7, 2025
d926422
chore(EtsyOptionsValidation): apply Review suggestions
DevTKSS Nov 7, 2025
3274b0c
test(EtsyProvider): Update tests accordingly to review suggestions an…
DevTKSS Nov 7, 2025
5020b47
chore: xml docs updates and update bundle.json with the placeholder v…
DevTKSS Nov 7, 2025
5cf8e94
chore: implement Options fed DetailedUserInfoEndpoint and set fallbac…
DevTKSS Nov 7, 2025
b6778e3
chore: fix test builds
DevTKSS Nov 7, 2025
77e5d3e
chore: set InlineData to magic string "urn:etsy:shop_id" because only…
DevTKSS Nov 8, 2025
0e7c558
chore(EtsyTests): apply workaround into PostConfigure test
DevTKSS Nov 8, 2025
99e2873
chore: create seperate named log methods
DevTKSS Nov 8, 2025
a499c03
docs(EtsyProvider): Add links to etsy provider docs and author, updat…
DevTKSS Nov 7, 2025
8f0c011
chore: applying PR rewording suggestion
DevTKSS Nov 9, 2025
6bb5ca6
chore: Resolve Merge Conflicts from sln to slnx migration
DevTKSS Nov 27, 2025
d6173cf
refactor: Add blank line in project file, remove unused usings and up…
DevTKSS Dec 2, 2025
c4a7323
chore: include user_id in Defaults Claims
DevTKSS Dec 2, 2025
b0b1b3f
chore: change DetailedUserInfoEndpoint to concatenated string instead…
DevTKSS Dec 2, 2025
25b9a45
revert(EtsyPostConfigureOptions): apply DetailedUserInfo Config via P…
DevTKSS Dec 2, 2025
868bce2
revert(EtsyTests): apply workaround into PostConfigure test
DevTKSS Dec 2, 2025
690633b
chore: remove tests for validating empty or not containing shop_r Opt…
DevTKSS Dec 2, 2025
74eaa4d
chore: add user_id claim mapping test case
DevTKSS Dec 2, 2025
5b80a6b
docs(etsy): Refactor to minimal guide
DevTKSS Dec 2, 2025
8bf2b2d
chore: remove image for docs and remove in slnx
DevTKSS Dec 2, 2025
e2cfde5
Merge branch 'aspnet-contrib:dev' into add-etsy-oauth-provider
DevTKSS Dec 7, 2025
e6b3cac
chore: fix typo
DevTKSS Dec 9, 2025
d7836a2
chore: applying PR rewording suggestion
DevTKSS Dec 9, 2025
88252a1
docs(etsy): Update Headings and table columns to match existing provi…
DevTKSS Dec 9, 2025
8676a4a
chore: Update xml docs and introduce default value for DetailedUserIn…
DevTKSS Dec 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions AspNet.Security.OAuth.Providers.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
<File Path="docs/docusign.md" />
<File Path="docs/dropbox.md" />
<File Path="docs/ebay.md" />
<File Path="docs/etsy.md" />
<File Path="docs/eveonline.md" />
<File Path="docs/foursquare.md" />
<File Path="docs/gitcode.md" />
Expand Down Expand Up @@ -120,6 +121,7 @@
<Project Path="src/AspNet.Security.OAuth.Docusign/AspNet.Security.OAuth.Docusign.csproj" />
<Project Path="src/AspNet.Security.OAuth.Dropbox/AspNet.Security.OAuth.Dropbox.csproj" />
<Project Path="src/AspNet.Security.OAuth.Ebay/AspNet.Security.OAuth.Ebay.csproj" />
<Project Path="src/AspNet.Security.OAuth.Etsy/AspNet.Security.OAuth.Etsy.csproj" />
<Project Path="src/AspNet.Security.OAuth.EVEOnline/AspNet.Security.OAuth.EVEOnline.csproj" />
<Project Path="src/AspNet.Security.OAuth.ExactOnline/AspNet.Security.OAuth.ExactOnline.csproj" />
<Project Path="src/AspNet.Security.OAuth.Feishu/AspNet.Security.OAuth.Feishu.csproj" />
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ We would love it if you could help contributing to this repository.
* [Robert Shade](https://github.com/robert-shade)
* [saber-wang](https://github.com/saber-wang)
* [Sinan](https://github.com/SH2015)
* [Sonja Schweitzer](https://github.com/DevTKSS)
* [Stefan](https://github.com/Schlurcher)
* [Steffen Wenz](https://github.com/swenz)
* [Tathagata Chakraborty](https://github.com/tatx)
Expand Down Expand Up @@ -182,6 +183,7 @@ If a provider you're looking for does not exist, consider making a PR to add one
| Docusign | [![NuGet](https://img.shields.io/nuget/v/AspNet.Security.OAuth.Docusign?logo=nuget&label=NuGet&color=blue)](https://www.nuget.org/packages/AspNet.Security.OAuth.Docusign/ "Download AspNet.Security.OAuth.Docusign from NuGet.org") | [![MyGet](https://img.shields.io/myget/aspnet-contrib/vpre/AspNet.Security.OAuth.Docusign?logo=nuget&label=MyGet&color=blue)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.Docusign "Download AspNet.Security.OAuth.Docusign from MyGet.org") | [Documentation](https://developers.docusign.com/platform/auth/ "Docusign developer documentation") |
| Dropbox | [![NuGet](https://img.shields.io/nuget/v/AspNet.Security.OAuth.Dropbox?logo=nuget&label=NuGet&color=blue)](https://www.nuget.org/packages/AspNet.Security.OAuth.Dropbox/ "Download AspNet.Security.OAuth.Dropbox from NuGet.org") | [![MyGet](https://img.shields.io/myget/aspnet-contrib/vpre/AspNet.Security.OAuth.Dropbox?logo=nuget&label=MyGet&color=blue)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.Dropbox "Download AspNet.Security.OAuth.Dropbox from MyGet.org") | [Documentation](https://www.dropbox.com/developers/reference/oauth-guide?_tk=guides_lp&_ad=deepdive2&_camp=oauth "Dropbox developer documentation") |
| eBay | [![NuGet](https://img.shields.io/nuget/v/AspNet.Security.OAuth.Ebay?logo=nuget&label=NuGet&color=blue)](https://www.nuget.org/packages/AspNet.Security.OAuth.Ebay/ "Download AspNet.Security.OAuth.Ebay from NuGet.org") | [![MyGet](https://img.shields.io/myget/aspnet-contrib/vpre/AspNet.Security.OAuth.Ebay?logo=nuget&label=MyGet&color=blue)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.Ebay "Download AspNet.Security.OAuth.Ebay from MyGet.org") | [Documentation](https://developer.ebay.com/api-docs/static/oauth-tokens.html "eBay developer documentation") |
| Etsy | [![NuGet](https://img.shields.io/nuget/v/AspNet.Security.OAuth.Etsy?logo=nuget&label=NuGet&color=blue)](https://www.nuget.org/packages/AspNet.Security.OAuth.Etsy/ "Download AspNet.Security.OAuth.Etsy from NuGet.org") | [![MyGet](https://img.shields.io/myget/aspnet-contrib/vpre/AspNet.Security.OAuth.Etsy?logo=nuget&label=MyGet&color=blue)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.Etsy "Download AspNet.Security.OAuth.Etsy from MyGet.org") | [Documentation](https://developers.etsy.com/documentation/essentials/authentication "Etsy developer documentation") |
| EVEOnline | [![NuGet](https://img.shields.io/nuget/v/AspNet.Security.OAuth.EVEOnline?logo=nuget&label=NuGet&color=blue)](https://www.nuget.org/packages/AspNet.Security.OAuth.EVEOnline/ "Download AspNet.Security.OAuth.EVEOnline from NuGet.org") | [![MyGet](https://img.shields.io/myget/aspnet-contrib/vpre/AspNet.Security.OAuth.EVEOnline?logo=nuget&label=MyGet&color=blue)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.EVEOnline "Download AspNet.Security.OAuth.EVEOnline from MyGet.org") | [Documentation](https://github.com/esi/esi-docs/blob/master/docs/sso/web_based_sso_flow.md "EVEOnline developer documentation") |
| ExactOnline | [![NuGet](https://img.shields.io/nuget/v/AspNet.Security.OAuth.ExactOnline?logo=nuget&label=NuGet&color=blue)](https://www.nuget.org/packages/AspNet.Security.OAuth.ExactOnline/ "Download AspNet.Security.OAuth.ExactOnline from NuGet.org") | [![MyGet](https://img.shields.io/myget/aspnet-contrib/vpre/AspNet.Security.OAuth.ExactOnline?logo=nuget&label=MyGet&color=blue)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.ExactOnline "Download AspNet.Security.OAuth.ExactOnline from MyGet.org") | [Documentation](https://support.exactonline.com/community/s/knowledge-base#All-All-DNO-Content-gettingstarted "ExactOnline developer documentation") |
| Feishu | [![NuGet](https://img.shields.io/nuget/v/AspNet.Security.OAuth.Feishu?logo=nuget&label=NuGet&color=blue)](https://www.nuget.org/packages/AspNet.Security.OAuth.Feishu/ "Download AspNet.Security.OAuth.Feishu from NuGet.org") | [![MyGet](https://img.shields.io/myget/aspnet-contrib/vpre/AspNet.Security.OAuth.Feishu?logo=nuget&label=MyGet&color=blue)](https://www.myget.org/feed/aspnet-contrib/package/nuget/AspNet.Security.OAuth.Feishu "Download AspNet.Security.OAuth.Feishu from MyGet.org") | [Documentation](https://open.feishu.cn/document/common-capabilities/sso/web-application-sso/web-app-overview "Feishu developer documentation") |
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ covered by the section above.
| Discord | _Optional_ | [Documentation](discord.md "Discord provider documentation") |
| Docusign | **Required** | [Documentation](docusign.md "Docusign provider documentation") |
| eBay | **Required** | [Documentation](ebay.md "eBay provider documentation") |
| Etsy | _Optional_ | [Documentation](etsy.md "Etsy provider documentation") |
| EVEOnline | _Optional_ | [Documentation](eveonline.md "EVEOnline provider documentation") |
| Foursquare | _Optional_ | [Documentation](foursquare.md "Foursquare provider documentation") |
| GitCode | _Optional_ | [Documentation](gitcode.md "GitCode provider documentation") |
Expand Down
55 changes: 55 additions & 0 deletions docs/etsy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Integrating the Etsy Provider

Etsy's OAuth implementation uses Authorization Code with **PKCE** and issues **refresh tokens**.

This provider enables PKCE by default and validates scopes to match Etsy's requirements.

- [Integrating the Etsy Provider](#integrating-the-etsy-provider)
- [Example](#example)
- [Required Additional Settings](#required-additional-settings)
- [Optional Settings](#optional-settings)
- [Quick Links](#quick-links)

## Example

```csharp
using AspNet.Security.OAuth.Etsy;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;

var builder = WebApplication.CreateBuilder(args);

builder.Services
.AddAuthentication(options => { /* Authentication options */ })
.AddEtsy(options =>
{
options.ClientId = "my-etsy-client-id";
options.ClientSecret = "my-etsy-client-secret"; // Optional as Etsy requires PKCE
options.IncludeDetailedUserInfo = true; // Optional to get first name, last name, email claims
options.ClaimActions.MapImageClaim(); // Optional Extension to map the image_url_75x75 claim, will not be mapped automatically
});
```

## Required Additional Settings

- You can obtain the Client ID (`keystring`) for your app by registering your application on [Etsy's developer portal](https://www.etsy.com/developers/your-apps).
- The ClientSecret (`shared secret` in the Etsy app details) is optional for public clients using PKCE.

## Optional Settings

| Property Name | Property Type | Description | Default Value |
|:--|:--|:--|:--|
| `IncludeDetailedUserInfo` | `bool` | Fetch extended profile data with auto-mapped claims (Email, GivenName, Surname). | `false` |
| `ClaimActions.MapImageClaim()` | Extension method | Map the `image_url_75x75` claim to `EtsyAuthenticationConstants.Claims.ImageUrl`. | Not mapped automatically |
| `DetailedUserInfoEndpoint` | `string` | Endpoint to retrieve detailed user information. | `https://openapi.etsy.com/v3/application/users/` |

Additional helpers are available via `EtsyAuthenticationConstants.Scopes.*` for Etsy OAuth scopes and `EtsyAuthenticationConstants.Claims.*` for claim type constants used for the `getMe` and `getUser` endpoints.

## Quick Links

| Resource | Link |
|:--|:--|
| Register your App on Etsy: | [Apps You've Made](https://www.etsy.com/developers/your-apps) |
| Official Etsy Authentication API Documentation: | [Etsy Developer Documentation](https://developers.etsy.com/documentation/essentials/authentication) |
| Requesting a Refresh OAuth Token: | [Etsy Refresh Token Guide](https://developers.etsy.com/documentation/essentials/authentication#requesting-a-refresh-oauth-token) |
| Etsy API Reference: | [Etsy API Reference](https://developers.etsy.com/documentation/reference) |
21 changes: 21 additions & 0 deletions src/AspNet.Security.OAuth.Etsy/AspNet.Security.OAuth.Etsy.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<PackageValidationBaselineVersion>10.1.0</PackageValidationBaselineVersion>
<TargetFrameworks>$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<!-- TODO Remove once published to NuGet.org -->
<DisablePackageBaselineValidation>true</DisablePackageBaselineValidation>
</PropertyGroup>

<PropertyGroup>
<Description>ASP.NET Core security middleware enabling Etsy authentication.</Description>
<Authors>Sonja Schweitzer</Authors>
<PackageTags>aspnetcore;authentication;etsy;oauth;security</PackageTags>
</PropertyGroup>

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All" />
</ItemGroup>

</Project>
24 changes: 24 additions & 0 deletions src/AspNet.Security.OAuth.Etsy/ClaimActionCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
* for more information concerning the license and the contributors participating to this project.
*/

using AspNet.Security.OAuth.Etsy;
using Microsoft.AspNetCore.Authentication.OAuth.Claims;

namespace Microsoft.Extensions.DependencyInjection;

/// <summary>
/// Provides extension methods for <see cref="ClaimActionCollection"/> to map Etsy API specific user claims.
/// </summary>
public static class ClaimActionCollectionExtensions
{
/// <summary>
/// Maps the Etsy user's profile image URL (75x75) to the <see cref="EtsyAuthenticationConstants.Claims.ImageUrl"/> claim.
/// </summary>
public static void MapImageClaim(this ClaimActionCollection collection)
{
collection.MapJsonKey(EtsyAuthenticationConstants.Claims.ImageUrl, "image_url_75x75");
}
}
94 changes: 94 additions & 0 deletions src/AspNet.Security.OAuth.Etsy/EtsyAuthenticationConstants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
* for more information concerning the license and the contributors participating to this project.
*/

namespace AspNet.Security.OAuth.Etsy;

/// <summary>
/// Contains constants specific to the <see cref="EtsyAuthenticationHandler"/>.
/// </summary>
public static class EtsyAuthenticationConstants
{
/// <summary>
/// Contains claim type constants specific to Etsy authentication.
/// </summary>
public static class Claims
{
/// <summary>The claim type for the user's Etsy user ID.</summary>
public static readonly string UserId = "urn:etsy:user_id";

/// <summary>The claim type for the user's Etsy shop ID.</summary>
public static readonly string ShopId = "urn:etsy:shop_id";

/// <summary>The claim type for the user's profile image URL.</summary>
public static readonly string ImageUrl = "urn:etsy:image_url";
}

/// <summary>
/// Contains <see href="https://developers.etsy.com/documentation/reference#section/Authentication/oauth2">Etsy OAuth Scopes</see> constants for Etsy authentication.
/// </summary>
public static class Scopes
{
/// <summary>See billing and shipping addresses</summary>
public static readonly string AddressRead = "address_r";

/// <summary>Update billing and shipping addresses</summary>
public static readonly string AddressWrite = "address_w";

/// <summary>See all billing statement data</summary>
public static readonly string BillingRead = "billing_r";

/// <summary>Read shopping carts</summary>
public static readonly string CartRead = "cart_r";

/// <summary>Add/Remove from shopping carts</summary>
public static readonly string CartWrite = "cart_w";

/// <summary>Read a user profile</summary>
public static readonly string EmailRead = "email_r";

/// <summary>See private favorites</summary>
public static readonly string FavoritesRead = "favorites_r";

/// <summary>Add/Remove favorites</summary>
public static readonly string FavoritesWrite = "favorites_w";

/// <summary>See purchase info in feedback</summary>
public static readonly string FeedbackRead = "feedback_r";

/// <summary>Delete listings</summary>
public static readonly string ListingsDelete = "listings_d";

/// <summary>See all listings (including expired etc)</summary>
public static readonly string ListingsRead = "listings_r";

/// <summary>Create/Edit listings</summary>
public static readonly string ListingsWrite = "listings_w";

/// <summary>See all profile data</summary>
public static readonly string ProfileRead = "profile_r";

/// <summary>Update user profile, avatar, etc</summary>
public static readonly string ProfileWrite = "profile_w";

/// <summary>See recommended listings</summary>
public static readonly string RecommendRead = "recommend_r";

/// <summary>Accept/Reject recommended listings</summary>
public static readonly string RecommendWrite = "recommend_w";

/// <summary>See private shop info</summary>
public static readonly string ShopsRead = "shops_r";

/// <summary>Update shop</summary>
public static readonly string ShopsWrite = "shops_w";

/// <summary>See all checkout/payment data</summary>
public static readonly string TransactionsRead = "transactions_r";

/// <summary>Update receipts</summary>
public static readonly string TransactionsWrite = "transactions_w";
}
}
53 changes: 53 additions & 0 deletions src/AspNet.Security.OAuth.Etsy/EtsyAuthenticationDefaults.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
* for more information concerning the license and the contributors participating to this project.
*/

namespace AspNet.Security.OAuth.Etsy;

/// <summary>
/// Default values used by the Etsy authentication middleware.
/// </summary>
public static class EtsyAuthenticationDefaults
{
/// <summary>
/// Default value for <see cref="AuthenticationScheme.Name"/>.
/// </summary>
public const string AuthenticationScheme = "Etsy";

/// <summary>
/// Default value for <see cref="AuthenticationScheme.DisplayName"/>.
/// </summary>
public static readonly string DisplayName = "Etsy";

/// <summary>
/// Default value for <see cref="AuthenticationSchemeOptions.ClaimsIssuer"/>.
/// </summary>
public static readonly string Issuer = "Etsy";

/// <summary>
/// Default value for <see cref="RemoteAuthenticationOptions.CallbackPath"/>.
/// </summary>
public static readonly string CallbackPath = "/signin-etsy";

/// <summary>
/// Default value for <see cref="OAuthOptions.AuthorizationEndpoint"/>.
/// </summary>
public static readonly string AuthorizationEndpoint = "https://www.etsy.com/oauth/connect";

/// <summary>
/// Default value for <see cref="OAuthOptions.TokenEndpoint"/>.
/// </summary>
public static readonly string TokenEndpoint = "https://openapi.etsy.com/v3/public/oauth/token";

/// <summary>
/// Default value for <see cref="OAuthOptions.UserInformationEndpoint"/> <see href="https://developers.etsy.com/documentation/reference/#operation/getMe">Etsy getMe Endpoint</see>.
/// </summary>
public static readonly string UserInformationEndpoint = "https://openapi.etsy.com/v3/application/users/me";

/// <summary>
/// Default value for receiving the user profile based upon a unique user ID <see href="https://developers.etsy.com/documentation/reference/#operation/getUser">getUser</see>.
/// </summary>
public static readonly string DetailedUserInfoEndpoint = "https://openapi.etsy.com/v3/application/users/";
}
Loading