Skip to content

Commit

Permalink
fix: implement offline scope in the way google expects (#3088)
Browse files Browse the repository at this point in the history
  • Loading branch information
tsearle authored Feb 14, 2023
1 parent fd37383 commit 39043d4
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 0 deletions.
47 changes: 47 additions & 0 deletions selfservice/strategy/oidc/provider_google.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@

package oidc

import (
"context"

gooidc "github.com/coreos/go-oidc"
"golang.org/x/oauth2"

"github.com/ory/x/stringslice"
)

type ProviderGoogle struct {
*ProviderGenericOIDC
}
Expand All @@ -19,3 +28,41 @@ func NewProviderGoogle(
},
}
}

func (g *ProviderGoogle) oauth2ConfigFromEndpoint(ctx context.Context, endpoint oauth2.Endpoint) *oauth2.Config {
scope := g.config.Scope
if !stringslice.Has(scope, gooidc.ScopeOpenID) {
scope = append(scope, gooidc.ScopeOpenID)
}

scope = stringslice.Filter(scope, func(s string) bool { return s == gooidc.ScopeOfflineAccess })

return &oauth2.Config{
ClientID: g.config.ClientID,
ClientSecret: g.config.ClientSecret,
Endpoint: endpoint,
Scopes: scope,
RedirectURL: g.config.Redir(g.reg.Config().OIDCRedirectURIBase(ctx)),
}
}

func (g *ProviderGoogle) OAuth2(ctx context.Context) (*oauth2.Config, error) {
p, err := g.provider(ctx)
if err != nil {
return nil, err
}

endpoint := p.Endpoint()
return g.oauth2ConfigFromEndpoint(ctx, endpoint), nil
}

func (g *ProviderGoogle) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
scope := g.config.Scope
options := g.ProviderGenericOIDC.AuthCodeURLOptions(r)

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

return options
}
55 changes: 55 additions & 0 deletions selfservice/strategy/oidc/provider_google_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package oidc_test

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"golang.org/x/oauth2"

"github.com/ory/kratos/internal"
"github.com/ory/kratos/selfservice/flow/login"
"github.com/ory/kratos/selfservice/strategy/oidc"
"github.com/ory/kratos/x"
)

func TestProviderGoogle_Scope(t *testing.T) {
_, reg := internal.NewFastRegistryWithMocks(t)

p := oidc.NewProviderGoogle(&oidc.Configuration{
Provider: "google",
ID: "valid",
ClientID: "client",
ClientSecret: "secret",
Mapper: "file://./stub/hydra.schema.json",
RequestedClaims: nil,
Scope: []string{"email", "profile", "offline_access"},
}, reg)

c, _ := p.OAuth2(context.Background())
assert.NotContains(t, c.Scopes, "offline_access")
}

func TestProviderGoogle_AccessType(t *testing.T) {
_, reg := internal.NewFastRegistryWithMocks(t)

p := oidc.NewProviderGoogle(&oidc.Configuration{
Provider: "google",
ID: "valid",
ClientID: "client",
ClientSecret: "secret",
Mapper: "file://./stub/hydra.schema.json",
RequestedClaims: nil,
Scope: []string{"email", "profile", "offline_access"},
}, reg)

r := &login.Flow{
ID: x.NewUUID(),
}

options := p.AuthCodeURLOptions(r)
assert.Contains(t, options, oauth2.AccessTypeOffline)
}

0 comments on commit 39043d4

Please sign in to comment.