From b8334e07c3b92165c8a6f4e473fc4d9209a55dd1 Mon Sep 17 00:00:00 2001 From: Ronald Burns <7757589+ronaldburns@users.noreply.github.com> Date: Sun, 17 Dec 2023 07:54:01 -0600 Subject: [PATCH 1/7] Update config.schema.json --- embedx/config.schema.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/embedx/config.schema.json b/embedx/config.schema.json index b8d767ef179a..97b51d82cb20 100644 --- a/embedx/config.schema.json +++ b/embedx/config.schema.json @@ -436,7 +436,8 @@ "dingtalk", "patreon", "linkedin", - "lark" + "lark", + "epic-games" ], "examples": ["google"] }, From 2a75d33fd33e41ff8a07e0826d01e0b174ff729b Mon Sep 17 00:00:00 2001 From: Ronald Burns <7757589+ronaldburns@users.noreply.github.com> Date: Sun, 17 Dec 2023 07:54:45 -0600 Subject: [PATCH 2/7] Update provider_config.go --- selfservice/strategy/oidc/provider_config.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/selfservice/strategy/oidc/provider_config.go b/selfservice/strategy/oidc/provider_config.go index c6fc84f762de..b1a17260d6c4 100644 --- a/selfservice/strategy/oidc/provider_config.go +++ b/selfservice/strategy/oidc/provider_config.go @@ -39,6 +39,7 @@ type Configuration struct { // - dingtalk // - linkedin // - patreon + // - epic-games Provider string `json:"provider"` // Label represents an optional label which can be used in the UI generation. @@ -154,6 +155,7 @@ var supportedProviders = map[string]func(config *Configuration, reg Dependencies "linkedin": NewProviderLinkedIn, "patreon": NewProviderPatreon, "lark": NewProviderLark, + "epic-games": NewProviderEpicGames, } func (c ConfigurationCollection) Provider(id string, reg Dependencies) (Provider, error) { From a6d7736fafc55e8da17f2b12203cadabb97309a9 Mon Sep 17 00:00:00 2001 From: Ronald Burns <7757589+ronaldburns@users.noreply.github.com> Date: Sun, 17 Dec 2023 07:55:26 -0600 Subject: [PATCH 3/7] Create provider_epic_games.go --- .../strategy/oidc/provider_epic_games.go | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 selfservice/strategy/oidc/provider_epic_games.go diff --git a/selfservice/strategy/oidc/provider_epic_games.go b/selfservice/strategy/oidc/provider_epic_games.go new file mode 100644 index 000000000000..a4f701533eee --- /dev/null +++ b/selfservice/strategy/oidc/provider_epic_games.go @@ -0,0 +1,118 @@ +// Copyright © 2023 Ory Corp +// SPDX-License-Identifier: Apache-2.0 + +package oidc + +import ( + "context" + "encoding/json" + "net/url" + + "github.com/hashicorp/go-retryablehttp" + + "github.com/ory/x/httpx" + + "github.com/pkg/errors" + "golang.org/x/oauth2" + + "github.com/ory/herodot" +) + +type ProviderEpicGames struct { + config *Configuration + reg Dependencies +} + +type EpicGamesIdentityResponse struct { + Data struct { + Attributes struct { + Email string `json:"email"` + FirstName string `json:"first_name"` + FullName string `json:"full_name"` + ImageUrl string `json:"image_url"` + LastName string `json:"last_name"` + } `json:"attributes"` + Id string `json:"id"` + Type string `json:"type"` + } `json:"data"` +} + +func NewProviderEpicGames( + config *Configuration, + reg Dependencies, +) Provider { + return &ProviderEpicGames{ + config: config, + reg: reg, + } +} + +func (d *ProviderEpicGames) Config() *Configuration { + return d.config +} + +func (d *ProviderEpicGames) oauth2(ctx context.Context) *oauth2.Config { + return &oauth2.Config{ + ClientID: d.config.ClientID, + ClientSecret: d.config.ClientSecret, + Endpoint: oauth2.Endpoint{ + AuthURL: "https://www.epicgames.com/id/authorize", + TokenURL: "https://api.epicgames.dev/epic/oauth/v1/token", + AuthStyle: oauth2.AuthStyleInHeader, + }, + RedirectURL: d.config.Redir(d.reg.Config().OIDCRedirectURIBase(ctx)), + Scopes: d.config.Scope, + } +} + +func (d *ProviderEpicGames) OAuth2(ctx context.Context) (*oauth2.Config, error) { + d.reg.Logger().WithField("provider", "epic-games").Trace("ProviderCreating new oauth2 configuration in OAuth2 method.") + return d.oauth2(ctx), nil +} + +func (d *ProviderEpicGames) Claims(ctx context.Context, exchange *oauth2.Token, query url.Values) (*Claims, error) { + identityUrl := "https://api.epicgames.dev/epic/oauth/v1/userInfo" + + o := d.oauth2(ctx) + client := d.reg.HTTPClient(ctx, httpx.ResilientClientWithClient(o.Client(ctx, exchange))) + + req, err := retryablehttp.NewRequest("GET", identityUrl, nil) + if err != nil { + return nil, errors.WithStack(herodot.ErrInternalServerError.WithReasonf("%s", err)) + } + req.Header.Add("Content-Type", "application/json") + req.Header.Add("Authorization", "Bearer "+exchange.AccessToken) + + res, err := client.Do(req) + if err != nil { + return nil, errors.WithStack(herodot.ErrInternalServerError.WithReasonf("%s", err)) + } + defer res.Body.Close() + + if err := logUpstreamError(d.reg.Logger(), res); err != nil { + return nil, err + } + + data := EpicGamesIdentityResponse{} + jsonErr := json.NewDecoder(res.Body).Decode(&data) + if jsonErr != nil { + return nil, errors.WithStack(herodot.ErrInternalServerError.WithReasonf("%s", jsonErr)) + } + + claims := &Claims{ + Issuer: "https://api.epicgames.dev/epic/oauth/v1", + Subject: data.Data.Id, + Name: data.Data.Attributes.FullName, + Email: data.Data.Attributes.Email, + GivenName: data.Data.Attributes.FirstName, + FamilyName: data.Data.Attributes.LastName, + LastName: data.Data.Attributes.LastName, + Picture: data.Data.Attributes.ImageUrl, + } + + return claims, nil +} + +func (g *ProviderEpicGames) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption { + return []oauth2.AuthCodeOption{} +} From 00d84adc826db83cdd0ec7f37e8bdefe6d9b894e Mon Sep 17 00:00:00 2001 From: Ronald Burns <7757589+ronaldburns@users.noreply.github.com> Date: Sun, 17 Dec 2023 07:55:45 -0600 Subject: [PATCH 4/7] Update provider_private_net_test.go --- selfservice/strategy/oidc/provider_private_net_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/selfservice/strategy/oidc/provider_private_net_test.go b/selfservice/strategy/oidc/provider_private_net_test.go index 1e1d71458ee9..570eac240269 100644 --- a/selfservice/strategy/oidc/provider_private_net_test.go +++ b/selfservice/strategy/oidc/provider_private_net_test.go @@ -79,6 +79,7 @@ func TestProviderPrivateIP(t *testing.T) { // VK uses a fixed token URL and does not use the issuer. // Yandex uses a fixed token URL and does not use the issuer. // NetID uses a fixed token URL and does not use the issuer. + // Epic Games uses a fixed token URL and does not use the issuer. } { t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { p := tc.p(tc.c) From 803f8302c7dd56f668a0aba10850fc4ce623e9e1 Mon Sep 17 00:00:00 2001 From: Ronald Burns <7757589+ronaldburns@users.noreply.github.com> Date: Sun, 17 Dec 2023 07:56:18 -0600 Subject: [PATCH 5/7] Update config.d.ts --- test/e2e/cypress/support/config.d.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/e2e/cypress/support/config.d.ts b/test/e2e/cypress/support/config.d.ts index 060cb12822bf..36cab1bbd089 100644 --- a/test/e2e/cypress/support/config.d.ts +++ b/test/e2e/cypress/support/config.d.ts @@ -207,7 +207,7 @@ export type SelfServiceOIDCProvider1 = { [k: string]: unknown | undefined } /** - * Can be one of github, github-app, gitlab, generic, google, microsoft, discord, slack, facebook, auth0, vk, yandex, apple, spotify, netid, dingtalk, patreon. + * Can be one of github, github-app, gitlab, generic, google, microsoft, discord, slack, facebook, auth0, vk, yandex, apple, spotify, netid, dingtalk, patreon, epic-games. */ export type Provider = | "github" @@ -229,6 +229,7 @@ export type Provider = | "patreon" | "linkedin" | "lark" + | "epic-games" export type OptionalStringWhichWillBeUsedWhenGeneratingLabelsForUIButtons = string /** From 979ce2d127dfbf8477fba662073cf864d740d062 Mon Sep 17 00:00:00 2001 From: Ronald Burns Date: Sun, 17 Dec 2023 08:19:03 -0600 Subject: [PATCH 6/7] Update provider_epic_games.go --- selfservice/strategy/oidc/provider_epic_games.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfservice/strategy/oidc/provider_epic_games.go b/selfservice/strategy/oidc/provider_epic_games.go index a4f701533eee..e780d1181a00 100644 --- a/selfservice/strategy/oidc/provider_epic_games.go +++ b/selfservice/strategy/oidc/provider_epic_games.go @@ -74,7 +74,7 @@ func (d *ProviderEpicGames) Claims(ctx context.Context, exchange *oauth2.Token, identityUrl := "https://api.epicgames.dev/epic/oauth/v1/userInfo" o := d.oauth2(ctx) - client := d.reg.HTTPClient(ctx, httpx.ResilientClientWithClient(o.Client(ctx, exchange))) + ctx, client := httpx.SetOAuth2(ctx, d.reg.HTTPClient(ctx), o, exchange) req, err := retryablehttp.NewRequest("GET", identityUrl, nil) if err != nil { From 5804347f33e28459ae0d09b738664f6f270b644c Mon Sep 17 00:00:00 2001 From: Ronald Burns Date: Sun, 17 Dec 2023 08:34:13 -0600 Subject: [PATCH 7/7] Update provider_epic_games.go --- .../strategy/oidc/provider_epic_games.go | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/selfservice/strategy/oidc/provider_epic_games.go b/selfservice/strategy/oidc/provider_epic_games.go index e780d1181a00..3909cc07524d 100644 --- a/selfservice/strategy/oidc/provider_epic_games.go +++ b/selfservice/strategy/oidc/provider_epic_games.go @@ -47,34 +47,34 @@ func NewProviderEpicGames( } } -func (d *ProviderEpicGames) Config() *Configuration { - return d.config +func (e *ProviderEpicGames) Config() *Configuration { + return e.config } -func (d *ProviderEpicGames) oauth2(ctx context.Context) *oauth2.Config { +func (e *ProviderEpicGames) oauth2(ctx context.Context) *oauth2.Config { return &oauth2.Config{ - ClientID: d.config.ClientID, - ClientSecret: d.config.ClientSecret, + ClientID: e.config.ClientID, + ClientSecret: e.config.ClientSecret, Endpoint: oauth2.Endpoint{ AuthURL: "https://www.epicgames.com/id/authorize", TokenURL: "https://api.epicgames.dev/epic/oauth/v1/token", AuthStyle: oauth2.AuthStyleInHeader, }, - RedirectURL: d.config.Redir(d.reg.Config().OIDCRedirectURIBase(ctx)), - Scopes: d.config.Scope, + RedirectURL: e.config.Redir(e.reg.Config().OIDCRedirectURIBase(ctx)), + Scopes: e.config.Scope, } } -func (d *ProviderEpicGames) OAuth2(ctx context.Context) (*oauth2.Config, error) { - d.reg.Logger().WithField("provider", "epic-games").Trace("ProviderCreating new oauth2 configuration in OAuth2 method.") - return d.oauth2(ctx), nil +func (e *ProviderEpicGames) OAuth2(ctx context.Context) (*oauth2.Config, error) { + e.reg.Logger().WithField("provider", "epic-games").Trace("ProviderCreating new oauth2 configuration in OAuth2 method.") + return e.oauth2(ctx), nil } -func (d *ProviderEpicGames) Claims(ctx context.Context, exchange *oauth2.Token, query url.Values) (*Claims, error) { +func (e *ProviderEpicGames) Claims(ctx context.Context, exchange *oauth2.Token, query url.Values) (*Claims, error) { identityUrl := "https://api.epicgames.dev/epic/oauth/v1/userInfo" - o := d.oauth2(ctx) - ctx, client := httpx.SetOAuth2(ctx, d.reg.HTTPClient(ctx), o, exchange) + o := e.oauth2(ctx) + ctx, client := httpx.SetOAuth2(ctx, e.reg.HTTPClient(ctx), o, exchange) req, err := retryablehttp.NewRequest("GET", identityUrl, nil) if err != nil { @@ -89,7 +89,7 @@ func (d *ProviderEpicGames) Claims(ctx context.Context, exchange *oauth2.Token, } defer res.Body.Close() - if err := logUpstreamError(d.reg.Logger(), res); err != nil { + if err := logUpstreamError(e.reg.Logger(), res); err != nil { return nil, err } @@ -113,6 +113,6 @@ func (d *ProviderEpicGames) Claims(ctx context.Context, exchange *oauth2.Token, return claims, nil } -func (g *ProviderEpicGames) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption { +func (e *ProviderEpicGames) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption { return []oauth2.AuthCodeOption{} }