Skip to content

Commit

Permalink
fix: support Auth0 connection url parameter (PS-28)
Browse files Browse the repository at this point in the history
  • Loading branch information
splaunov committed May 15, 2024
1 parent d9dbaad commit 4e86e2f
Show file tree
Hide file tree
Showing 20 changed files with 79 additions and 42 deletions.
5 changes: 5 additions & 0 deletions embedx/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,11 @@
"enum": ["id_token", "userinfo"],
"default": "id_token",
"examples": ["id_token", "userinfo"]
},
"upstream_parameters": {
"title": "Parameters to be passed to OIDC provider as part of auth code URL",
"type": "object",
"additionalProperties": true
}
},
"additionalProperties": false,
Expand Down
2 changes: 1 addition & 1 deletion selfservice/strategy/oidc/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type Provider interface {

type OAuth2Provider interface {
Provider
AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption
AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error)
OAuth2(ctx context.Context) (*oauth2.Config, error)
Claims(ctx context.Context, exchange *oauth2.Token, query url.Values) (*Claims, error)
}
Expand Down
4 changes: 2 additions & 2 deletions selfservice/strategy/oidc/provider_apple.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func (a *ProviderApple) OAuth2(ctx context.Context) (*oauth2.Config, error) {
return a.oauth2(ctx)
}

func (a *ProviderApple) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
func (a *ProviderApple) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
var options []oauth2.AuthCodeOption

if isForced(r) {
Expand All @@ -109,7 +109,7 @@ func (a *ProviderApple) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
}
}

return options
return options, nil
}

func (a *ProviderApple) Claims(ctx context.Context, exchange *oauth2.Token, query url.Values) (*Claims, error) {
Expand Down
3 changes: 3 additions & 0 deletions selfservice/strategy/oidc/provider_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ type Configuration struct {
// endpoint to get the claims) or `id_token` (takes the claims from the id
// token). It defaults to `id_token`.
ClaimsSource string `json:"claims_source"`

// Parameters to be passed to OIDC provider as part of auth code URL
UpstreamParameters json.RawMessage `json:"upstream_parameters"`
}

func (p Configuration) Redir(public *url.URL) string {
Expand Down
4 changes: 2 additions & 2 deletions selfservice/strategy/oidc/provider_dingtalk.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ func (g *ProviderDingTalk) oauth2(ctx context.Context) *oauth2.Config {
}
}

func (g *ProviderDingTalk) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
func (g *ProviderDingTalk) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
return []oauth2.AuthCodeOption{
oauth2.SetAuthURLParam("prompt", "consent"),
}
}, nil
}

func (g *ProviderDingTalk) OAuth2(ctx context.Context) (*oauth2.Config, error) {
Expand Down
6 changes: 3 additions & 3 deletions selfservice/strategy/oidc/provider_discord.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ func (d *ProviderDiscord) OAuth2(ctx context.Context) (*oauth2.Config, error) {
return d.oauth2(ctx), nil
}

func (d *ProviderDiscord) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
func (d *ProviderDiscord) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
if isForced(r) {
return []oauth2.AuthCodeOption{
oauth2.SetAuthURLParam("prompt", "consent"),
}
}, nil
}
return []oauth2.AuthCodeOption{
oauth2.SetAuthURLParam("prompt", "none"),
}
}, nil
}

func (d *ProviderDiscord) Claims(ctx context.Context, exchange *oauth2.Token, query url.Values) (*Claims, error) {
Expand Down
15 changes: 13 additions & 2 deletions selfservice/strategy/oidc/provider_generic_oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package oidc

import (
"context"
"encoding/json"
"net/url"

"github.com/pkg/errors"
Expand Down Expand Up @@ -83,7 +84,7 @@ func (g *ProviderGenericOIDC) OAuth2(ctx context.Context) (*oauth2.Config, error
return g.oauth2ConfigFromEndpoint(ctx, endpoint), nil
}

func (g *ProviderGenericOIDC) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
func (g *ProviderGenericOIDC) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
var options []oauth2.AuthCodeOption

if isForced(r) {
Expand All @@ -93,7 +94,17 @@ func (g *ProviderGenericOIDC) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption
options = append(options, oauth2.SetAuthURLParam("claims", string(g.config.RequestedClaims)))
}

return options
if len(g.config.UpstreamParameters) != 0 {
var params map[string]string
if err := json.Unmarshal(g.config.UpstreamParameters, &params); err != nil {
return nil, err
}
for key, value := range params {
options = append(options, oauth2.SetAuthURLParam(key, value))
}
}

return options, nil
}

func (g *ProviderGenericOIDC) verifyAndDecodeClaimsWithProvider(ctx context.Context, provider *gooidc.Provider, raw string) (*Claims, error) {
Expand Down
26 changes: 18 additions & 8 deletions selfservice/strategy/oidc/provider_generic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,20 @@ func makeOIDCClaims() json.RawMessage {

func makeAuthCodeURL(t *testing.T, r *login.Flow, reg *driver.RegistryDefault) string {
p := oidc.NewProviderGenericOIDC(&oidc.Configuration{
Provider: "generic",
ID: "valid",
ClientID: "client",
ClientSecret: "secret",
IssuerURL: "https://accounts.google.com",
Mapper: "file://./stub/hydra.schema.json",
RequestedClaims: makeOIDCClaims(),
Provider: "generic",
ID: "valid",
ClientID: "client",
ClientSecret: "secret",
IssuerURL: "https://accounts.google.com",
Mapper: "file://./stub/hydra.schema.json",
RequestedClaims: makeOIDCClaims(),
UpstreamParameters: json.RawMessage(`{"connection": "c1"}`),
}, reg)
c, err := p.(oidc.OAuth2Provider).OAuth2(context.Background())
require.NoError(t, err)
return c.AuthCodeURL("state", p.(oidc.OAuth2Provider).AuthCodeURLOptions(r)...)
options, err := p.(oidc.OAuth2Provider).AuthCodeURLOptions(r)
require.NoError(t, err)
return c.AuthCodeURL("state", options...)
}

func TestProviderGenericOIDC_AddAuthCodeURLOptions(t *testing.T) {
Expand Down Expand Up @@ -93,4 +96,11 @@ func TestProviderGenericOIDC_AddAuthCodeURLOptions(t *testing.T) {
}
assert.Contains(t, makeAuthCodeURL(t, r, reg), "claims="+url.QueryEscape(string(makeOIDCClaims())))
})

t.Run("case=expect connection to be set", func(t *testing.T) {
r := &login.Flow{
ID: x.NewUUID(),
}
assert.Contains(t, makeAuthCodeURL(t, r, reg), "connection=c1")
})
}
4 changes: 2 additions & 2 deletions selfservice/strategy/oidc/provider_github.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ func (g *ProviderGitHub) OAuth2(ctx context.Context) (*oauth2.Config, error) {
return g.oauth2(ctx), nil
}

func (g *ProviderGitHub) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
return []oauth2.AuthCodeOption{}
func (g *ProviderGitHub) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
return []oauth2.AuthCodeOption{}, nil
}

func (g *ProviderGitHub) Claims(ctx context.Context, exchange *oauth2.Token, query url.Values) (*Claims, error) {
Expand Down
4 changes: 2 additions & 2 deletions selfservice/strategy/oidc/provider_github_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ func (g *ProviderGitHubApp) OAuth2(ctx context.Context) (*oauth2.Config, error)
return g.oauth2(ctx), nil
}

func (g *ProviderGitHubApp) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
return []oauth2.AuthCodeOption{}
func (g *ProviderGitHubApp) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
return []oauth2.AuthCodeOption{}, nil
}

func (g *ProviderGitHubApp) Claims(ctx context.Context, exchange *oauth2.Token, query url.Values) (*Claims, error) {
Expand Down
9 changes: 6 additions & 3 deletions selfservice/strategy/oidc/provider_google.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,18 @@ func (g *ProviderGoogle) OAuth2(ctx context.Context) (*oauth2.Config, error) {
return g.oauth2ConfigFromEndpoint(ctx, endpoint), nil
}

func (g *ProviderGoogle) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
func (g *ProviderGoogle) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
scope := g.config.Scope
options := g.ProviderGenericOIDC.AuthCodeURLOptions(r)
options, err := g.ProviderGenericOIDC.AuthCodeURLOptions(r)
if err != nil {
return nil, err
}

if stringslice.Has(scope, gooidc.ScopeOfflineAccess) {
options = append(options, oauth2.AccessTypeOffline)
}

return options
return options, nil
}

var _ IDTokenVerifier = new(ProviderGoogle)
Expand Down
3 changes: 2 additions & 1 deletion selfservice/strategy/oidc/provider_google_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ func TestProviderGoogle_AccessType(t *testing.T) {
ID: x.NewUUID(),
}

options := p.(oidc.OAuth2Provider).AuthCodeURLOptions(r)
options, err := p.(oidc.OAuth2Provider).AuthCodeURLOptions(r)
require.NoError(t, err)
assert.Contains(t, options, oauth2.AccessTypeOffline)
}

Expand Down
4 changes: 2 additions & 2 deletions selfservice/strategy/oidc/provider_lark.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,6 @@ func (g *ProviderLark) Claims(ctx context.Context, exchange *oauth2.Token, query
}, nil
}

func (pl *ProviderLark) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
return []oauth2.AuthCodeOption{}
func (pl *ProviderLark) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
return []oauth2.AuthCodeOption{}, nil
}
4 changes: 2 additions & 2 deletions selfservice/strategy/oidc/provider_linkedin.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ func (l *ProviderLinkedIn) OAuth2(ctx context.Context) (*oauth2.Config, error) {
return l.oauth2(ctx), nil
}

func (l *ProviderLinkedIn) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
return []oauth2.AuthCodeOption{}
func (l *ProviderLinkedIn) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
return []oauth2.AuthCodeOption{}, nil
}

func (l *ProviderLinkedIn) fetch(ctx context.Context, client *retryablehttp.Client, url string, result interface{}) (err error) {
Expand Down
6 changes: 3 additions & 3 deletions selfservice/strategy/oidc/provider_patreon.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@ func (d *ProviderPatreon) OAuth2(ctx context.Context) (*oauth2.Config, error) {
return d.oauth2(ctx), nil
}

func (d *ProviderPatreon) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
func (d *ProviderPatreon) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
if isForced(r) {
return []oauth2.AuthCodeOption{
oauth2.SetAuthURLParam("prompt", "consent"),
}
}, nil
}
return []oauth2.AuthCodeOption{
oauth2.SetAuthURLParam("prompt", "none"),
}
}, nil
}

func (d *ProviderPatreon) Claims(ctx context.Context, exchange *oauth2.Token, query url.Values) (*Claims, error) {
Expand Down
4 changes: 2 additions & 2 deletions selfservice/strategy/oidc/provider_slack.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ func (d *ProviderSlack) OAuth2(ctx context.Context) (*oauth2.Config, error) {
return d.oauth2(ctx), nil
}

func (d *ProviderSlack) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
return []oauth2.AuthCodeOption{}
func (d *ProviderSlack) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
return []oauth2.AuthCodeOption{}, nil
}

func (d *ProviderSlack) Claims(ctx context.Context, exchange *oauth2.Token, query url.Values) (*Claims, error) {
Expand Down
4 changes: 2 additions & 2 deletions selfservice/strategy/oidc/provider_spotify.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ func (g *ProviderSpotify) OAuth2(ctx context.Context) (*oauth2.Config, error) {
return g.oauth2(ctx), nil
}

func (g *ProviderSpotify) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
return []oauth2.AuthCodeOption{}
func (g *ProviderSpotify) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
return []oauth2.AuthCodeOption{}, nil
}

func (g *ProviderSpotify) Claims(ctx context.Context, exchange *oauth2.Token, query url.Values) (*Claims, error) {
Expand Down
4 changes: 2 additions & 2 deletions selfservice/strategy/oidc/provider_vk.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ func (g *ProviderVK) oauth2(ctx context.Context) *oauth2.Config {
}
}

func (g *ProviderVK) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
return []oauth2.AuthCodeOption{}
func (g *ProviderVK) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
return []oauth2.AuthCodeOption{}, nil
}

func (g *ProviderVK) OAuth2(ctx context.Context) (*oauth2.Config, error) {
Expand Down
4 changes: 2 additions & 2 deletions selfservice/strategy/oidc/provider_yandex.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ func (g *ProviderYandex) oauth2(ctx context.Context) *oauth2.Config {
}
}

func (g *ProviderYandex) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
return []oauth2.AuthCodeOption{}
func (g *ProviderYandex) AuthCodeURLOptions(r ider) ([]oauth2.AuthCodeOption, error) {
return []oauth2.AuthCodeOption{}, nil
}

func (g *ProviderYandex) OAuth2(ctx context.Context) (*oauth2.Config, error) {
Expand Down
6 changes: 5 additions & 1 deletion selfservice/strategy/oidc/strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,11 @@ func getAuthRedirectURL(ctx context.Context, provider Provider, req ider, state
return "", err
}

return c.AuthCodeURL(state.String(), append(UpstreamParameters(upstreamParameters), p.AuthCodeURLOptions(req)...)...), nil
options, err := p.AuthCodeURLOptions(req)
if err != nil {
return "", nil
}
return c.AuthCodeURL(state.String(), append(UpstreamParameters(upstreamParameters), options...)...), nil
case OAuth1Provider:
return p.AuthURL(ctx, state.String())
default:
Expand Down

0 comments on commit 4e86e2f

Please sign in to comment.