authorize and callback endpoints now handle the offline_access scope
- This is in preparation for the token endpoint to support the refresh grant Signed-off-by: Ryan Richard <richardry@vmware.com>
This commit is contained in:
parent
6a90a10123
commit
d91baba240
@ -9,6 +9,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
coreosoidc "github.com/coreos/go-oidc"
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/handler/openid"
|
"github.com/ory/fosite/handler/openid"
|
||||||
"github.com/ory/fosite/token/jwt"
|
"github.com/ory/fosite/token/jwt"
|
||||||
@ -57,7 +58,10 @@ func NewHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Grant the openid scope (for now) if they asked for it so that `NewAuthorizeResponse` will perform its OIDC validations.
|
// Grant the openid scope (for now) if they asked for it so that `NewAuthorizeResponse` will perform its OIDC validations.
|
||||||
grantOpenIDScopeIfRequested(authorizeRequester)
|
oidc.GrantScopeIfRequested(authorizeRequester, coreosoidc.ScopeOpenID)
|
||||||
|
// There don't seem to be any validations inside `NewAuthorizeResponse` related to the offline_access scope
|
||||||
|
// at this time, however we will temporarily grant the scope just in case that changes in a future release of fosite.
|
||||||
|
oidc.GrantScopeIfRequested(authorizeRequester, coreosoidc.ScopeOfflineAccess)
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
_, err = oauthHelper.NewAuthorizeResponse(r.Context(), authorizeRequester, &openid.DefaultSession{
|
_, err = oauthHelper.NewAuthorizeResponse(r.Context(), authorizeRequester, &openid.DefaultSession{
|
||||||
@ -148,14 +152,6 @@ func readCSRFCookie(r *http.Request, codec oidc.Codec) csrftoken.CSRFToken {
|
|||||||
return csrfFromCookie
|
return csrfFromCookie
|
||||||
}
|
}
|
||||||
|
|
||||||
func grantOpenIDScopeIfRequested(authorizeRequester fosite.AuthorizeRequester) {
|
|
||||||
for _, scope := range authorizeRequester.GetRequestedScopes() {
|
|
||||||
if scope == "openid" {
|
|
||||||
authorizeRequester.GrantScope(scope)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func chooseUpstreamIDP(idpListGetter oidc.IDPListGetter) (provider.UpstreamOIDCIdentityProviderI, error) {
|
func chooseUpstreamIDP(idpListGetter oidc.IDPListGetter) (provider.UpstreamOIDCIdentityProviderI, error) {
|
||||||
allUpstreamIDPs := idpListGetter.GetIDPList()
|
allUpstreamIDPs := idpListGetter.GetIDPList()
|
||||||
if len(allUpstreamIDPs) == 0 {
|
if len(allUpstreamIDPs) == 0 {
|
||||||
|
@ -119,7 +119,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
|||||||
Name: "some-idp",
|
Name: "some-idp",
|
||||||
ClientID: "some-client-id",
|
ClientID: "some-client-id",
|
||||||
AuthorizationURL: *upstreamAuthURL,
|
AuthorizationURL: *upstreamAuthURL,
|
||||||
Scopes: []string{"scope1", "scope2"},
|
Scopes: []string{"scope1", "scope2"}, // the scopes to request when starting the upstream authorization flow
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure fosite the same way that the production code would, using NullStorage to turn off storage.
|
// Configure fosite the same way that the production code would, using NullStorage to turn off storage.
|
||||||
@ -372,6 +372,26 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
|||||||
wantUpstreamStateParamInLocationHeader: true,
|
wantUpstreamStateParamInLocationHeader: true,
|
||||||
wantBodyStringWithLocationInHref: true,
|
wantBodyStringWithLocationInHref: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "happy path when downstream requested scopes include offline_access",
|
||||||
|
issuer: downstreamIssuer,
|
||||||
|
idpListGetter: oidctestutil.NewIDPListGetter(&upstreamOIDCIdentityProvider),
|
||||||
|
generateCSRF: happyCSRFGenerator,
|
||||||
|
generatePKCE: happyPKCEGenerator,
|
||||||
|
generateNonce: happyNonceGenerator,
|
||||||
|
stateEncoder: happyStateEncoder,
|
||||||
|
cookieEncoder: happyCookieEncoder,
|
||||||
|
method: http.MethodGet,
|
||||||
|
path: modifiedHappyGetRequestPath(map[string]string{"scope": "openid offline_access"}),
|
||||||
|
wantStatus: http.StatusFound,
|
||||||
|
wantContentType: "text/html; charset=utf-8",
|
||||||
|
wantCSRFValueInCookieHeader: happyCSRF,
|
||||||
|
wantLocationHeader: expectedRedirectLocation(expectedUpstreamStateParam(map[string]string{
|
||||||
|
"scope": "openid offline_access",
|
||||||
|
}, "", "")),
|
||||||
|
wantUpstreamStateParamInLocationHeader: true,
|
||||||
|
wantBodyStringWithLocationInHref: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "downstream redirect uri does not match what is configured for client",
|
name: "downstream redirect uri does not match what is configured for client",
|
||||||
issuer: downstreamIssuer,
|
issuer: downstreamIssuer,
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
coreosoidc "github.com/coreos/go-oidc"
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/handler/openid"
|
"github.com/ory/fosite/handler/openid"
|
||||||
"github.com/ory/fosite/token/jwt"
|
"github.com/ory/fosite/token/jwt"
|
||||||
@ -70,8 +71,9 @@ func NewHandler(
|
|||||||
return httperr.New(http.StatusBadRequest, "error using state downstream auth params")
|
return httperr.New(http.StatusBadRequest, "error using state downstream auth params")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grant the openid scope only if it was requested.
|
// Automatically grant the openid and offline_access scopes, but only if they were requested.
|
||||||
grantOpenIDScopeIfRequested(authorizeRequester)
|
oidc.GrantScopeIfRequested(authorizeRequester, coreosoidc.ScopeOpenID)
|
||||||
|
oidc.GrantScopeIfRequested(authorizeRequester, coreosoidc.ScopeOfflineAccess)
|
||||||
|
|
||||||
token, err := upstreamIDPConfig.ExchangeAuthcodeAndValidateTokens(
|
token, err := upstreamIDPConfig.ExchangeAuthcodeAndValidateTokens(
|
||||||
r.Context(),
|
r.Context(),
|
||||||
@ -189,14 +191,6 @@ func readState(r *http.Request, stateDecoder oidc.Decoder) (*oidc.UpstreamStateP
|
|||||||
return &state, nil
|
return &state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func grantOpenIDScopeIfRequested(authorizeRequester fosite.AuthorizeRequester) {
|
|
||||||
for _, scope := range authorizeRequester.GetRequestedScopes() {
|
|
||||||
if scope == "openid" {
|
|
||||||
authorizeRequester.GrantScope(scope)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUsernameFromUpstreamIDToken(
|
func getUsernameFromUpstreamIDToken(
|
||||||
upstreamIDPConfig provider.UpstreamOIDCIdentityProviderI,
|
upstreamIDPConfig provider.UpstreamOIDCIdentityProviderI,
|
||||||
idTokenClaims map[string]interface{},
|
idTokenClaims map[string]interface{},
|
||||||
|
@ -66,7 +66,8 @@ const (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
upstreamGroupMembership = []string{"test-pinniped-group-0", "test-pinniped-group-1"}
|
upstreamGroupMembership = []string{"test-pinniped-group-0", "test-pinniped-group-1"}
|
||||||
happyDownstreamScopesRequested = []string{"openid", "profile", "email"}
|
happyDownstreamScopesRequested = []string{"openid"}
|
||||||
|
happyDownstreamScopesGranted = []string{"openid"}
|
||||||
|
|
||||||
happyDownstreamRequestParamsQuery = url.Values{
|
happyDownstreamRequestParamsQuery = url.Values{
|
||||||
"response_type": []string{"code"},
|
"response_type": []string{"code"},
|
||||||
@ -127,7 +128,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
wantStatus int
|
wantStatus int
|
||||||
wantBody string
|
wantBody string
|
||||||
wantRedirectLocationRegexp string
|
wantRedirectLocationRegexp string
|
||||||
wantGrantedOpenidScope bool
|
wantDownstreamGrantedScopes []string
|
||||||
wantDownstreamIDTokenSubject string
|
wantDownstreamIDTokenSubject string
|
||||||
wantDownstreamIDTokenGroups []string
|
wantDownstreamIDTokenGroups []string
|
||||||
wantDownstreamRequestedScopes []string
|
wantDownstreamRequestedScopes []string
|
||||||
@ -145,11 +146,11 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
csrfCookie: happyCSRFCookie,
|
csrfCookie: happyCSRFCookie,
|
||||||
wantStatus: http.StatusFound,
|
wantStatus: http.StatusFound,
|
||||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||||
wantGrantedOpenidScope: true,
|
|
||||||
wantBody: "",
|
wantBody: "",
|
||||||
wantDownstreamIDTokenSubject: upstreamUsername,
|
wantDownstreamIDTokenSubject: upstreamUsername,
|
||||||
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
||||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||||
|
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||||
wantDownstreamNonce: downstreamNonce,
|
wantDownstreamNonce: downstreamNonce,
|
||||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||||
@ -163,11 +164,11 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
csrfCookie: happyCSRFCookie,
|
csrfCookie: happyCSRFCookie,
|
||||||
wantStatus: http.StatusFound,
|
wantStatus: http.StatusFound,
|
||||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||||
wantGrantedOpenidScope: true,
|
|
||||||
wantBody: "",
|
wantBody: "",
|
||||||
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + upstreamSubject,
|
wantDownstreamIDTokenSubject: upstreamIssuer + "?sub=" + upstreamSubject,
|
||||||
wantDownstreamIDTokenGroups: nil,
|
wantDownstreamIDTokenGroups: nil,
|
||||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||||
|
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||||
wantDownstreamNonce: downstreamNonce,
|
wantDownstreamNonce: downstreamNonce,
|
||||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||||
@ -181,11 +182,11 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
csrfCookie: happyCSRFCookie,
|
csrfCookie: happyCSRFCookie,
|
||||||
wantStatus: http.StatusFound,
|
wantStatus: http.StatusFound,
|
||||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||||
wantGrantedOpenidScope: true,
|
|
||||||
wantBody: "",
|
wantBody: "",
|
||||||
wantDownstreamIDTokenSubject: upstreamSubject,
|
wantDownstreamIDTokenSubject: upstreamSubject,
|
||||||
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
||||||
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
|
||||||
|
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
|
||||||
wantDownstreamNonce: downstreamNonce,
|
wantDownstreamNonce: downstreamNonce,
|
||||||
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||||
@ -316,6 +317,28 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||||
wantExchangeAndValidateTokensCall: happyExchangeAndValidateTokensArgs,
|
wantExchangeAndValidateTokensCall: happyExchangeAndValidateTokensArgs,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "state's downstream auth params also included offline_access scope",
|
||||||
|
idp: happyUpstream().Build(),
|
||||||
|
method: http.MethodGet,
|
||||||
|
path: newRequestPath().
|
||||||
|
WithState(
|
||||||
|
happyUpstreamStateParam().
|
||||||
|
WithAuthorizeRequestParams(shallowCopyAndModifyQuery(happyDownstreamRequestParamsQuery, map[string]string{"scope": "openid offline_access"}).Encode()).
|
||||||
|
Build(t, happyStateCodec),
|
||||||
|
).String(),
|
||||||
|
csrfCookie: happyCSRFCookie,
|
||||||
|
wantStatus: http.StatusFound,
|
||||||
|
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=openid%20offline_access&state=` + happyDownstreamState,
|
||||||
|
wantDownstreamIDTokenSubject: upstreamUsername,
|
||||||
|
wantDownstreamRequestedScopes: []string{"openid", "offline_access"},
|
||||||
|
wantDownstreamGrantedScopes: []string{"openid", "offline_access"},
|
||||||
|
wantDownstreamIDTokenGroups: upstreamGroupMembership,
|
||||||
|
wantDownstreamNonce: downstreamNonce,
|
||||||
|
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
|
||||||
|
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
|
||||||
|
wantExchangeAndValidateTokensCall: happyExchangeAndValidateTokensArgs,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "the UpstreamOIDCProvider CRD has been deleted",
|
name: "the UpstreamOIDCProvider CRD has been deleted",
|
||||||
idp: otherUpstreamOIDCIdentityProvider,
|
idp: otherUpstreamOIDCIdentityProvider,
|
||||||
@ -481,7 +504,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
|
|
||||||
// Several Secrets should have been created
|
// Several Secrets should have been created
|
||||||
expectedNumberOfCreatedSecrets := 2
|
expectedNumberOfCreatedSecrets := 2
|
||||||
if test.wantGrantedOpenidScope {
|
if includesOpenIDScope(test.wantDownstreamGrantedScopes) {
|
||||||
expectedNumberOfCreatedSecrets++
|
expectedNumberOfCreatedSecrets++
|
||||||
}
|
}
|
||||||
require.Len(t, client.Actions(), expectedNumberOfCreatedSecrets)
|
require.Len(t, client.Actions(), expectedNumberOfCreatedSecrets)
|
||||||
@ -493,7 +516,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
t,
|
t,
|
||||||
oauthStore,
|
oauthStore,
|
||||||
authcodeDataAndSignature[1], // Authcode store key is authcode signature
|
authcodeDataAndSignature[1], // Authcode store key is authcode signature
|
||||||
test.wantGrantedOpenidScope,
|
test.wantDownstreamGrantedScopes,
|
||||||
test.wantDownstreamIDTokenSubject,
|
test.wantDownstreamIDTokenSubject,
|
||||||
test.wantDownstreamIDTokenGroups,
|
test.wantDownstreamIDTokenGroups,
|
||||||
test.wantDownstreamRequestedScopes,
|
test.wantDownstreamRequestedScopes,
|
||||||
@ -513,7 +536,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// One IDSession should have been stored, if the downstream actually requested the "openid" scope
|
// One IDSession should have been stored, if the downstream actually requested the "openid" scope
|
||||||
if test.wantGrantedOpenidScope {
|
if includesOpenIDScope(test.wantDownstreamGrantedScopes) {
|
||||||
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: openidconnect.TypeLabelValue}, 1)
|
testutil.RequireNumberOfSecretsMatchingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: openidconnect.TypeLabelValue}, 1)
|
||||||
|
|
||||||
validateIDSessionStorage(
|
validateIDSessionStorage(
|
||||||
@ -530,6 +553,15 @@ func TestCallbackEndpoint(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func includesOpenIDScope(scopes []string) bool {
|
||||||
|
for _, scope := range scopes {
|
||||||
|
if scope == "openid" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type requestPath struct {
|
type requestPath struct {
|
||||||
code, state *string
|
code, state *string
|
||||||
}
|
}
|
||||||
@ -704,7 +736,7 @@ func validateAuthcodeStorage(
|
|||||||
t *testing.T,
|
t *testing.T,
|
||||||
oauthStore *oidc.KubeStorage,
|
oauthStore *oidc.KubeStorage,
|
||||||
storeKey string,
|
storeKey string,
|
||||||
wantGrantedOpenidScope bool,
|
wantDownstreamGrantedScopes []string,
|
||||||
wantDownstreamIDTokenSubject string,
|
wantDownstreamIDTokenSubject string,
|
||||||
wantDownstreamIDTokenGroups []string,
|
wantDownstreamIDTokenGroups []string,
|
||||||
wantDownstreamRequestedScopes []string,
|
wantDownstreamRequestedScopes []string,
|
||||||
@ -719,11 +751,7 @@ func validateAuthcodeStorage(
|
|||||||
storedRequestFromAuthcode, storedSessionFromAuthcode := castStoredAuthorizeRequest(t, storedAuthorizeRequestFromAuthcode)
|
storedRequestFromAuthcode, storedSessionFromAuthcode := castStoredAuthorizeRequest(t, storedAuthorizeRequestFromAuthcode)
|
||||||
|
|
||||||
// Check which scopes were granted.
|
// Check which scopes were granted.
|
||||||
if wantGrantedOpenidScope {
|
require.ElementsMatch(t, wantDownstreamGrantedScopes, storedRequestFromAuthcode.GetGrantedScopes())
|
||||||
require.Contains(t, storedRequestFromAuthcode.GetGrantedScopes(), "openid")
|
|
||||||
} else {
|
|
||||||
require.NotContains(t, storedRequestFromAuthcode.GetGrantedScopes(), "openid")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check all the other fields of the stored request.
|
// Check all the other fields of the stored request.
|
||||||
require.NotEmpty(t, storedRequestFromAuthcode.ID)
|
require.NotEmpty(t, storedRequestFromAuthcode.ID)
|
||||||
|
@ -28,7 +28,7 @@ func TestNullStorage_GetClient(t *testing.T) {
|
|||||||
RedirectURIs: []string{"http://127.0.0.1/callback"},
|
RedirectURIs: []string{"http://127.0.0.1/callback"},
|
||||||
ResponseTypes: []string{"code"},
|
ResponseTypes: []string{"code"},
|
||||||
GrantTypes: []string{"authorization_code"},
|
GrantTypes: []string{"authorization_code"},
|
||||||
Scopes: []string{"openid", "profile", "email"},
|
Scopes: []string{"openid", "offline_access", "profile", "email"},
|
||||||
},
|
},
|
||||||
TokenEndpointAuthMethod: "none",
|
TokenEndpointAuthMethod: "none",
|
||||||
},
|
},
|
||||||
|
@ -7,6 +7,7 @@ package oidc
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
coreosoidc "github.com/coreos/go-oidc"
|
||||||
"github.com/ory/fosite"
|
"github.com/ory/fosite"
|
||||||
"github.com/ory/fosite/compose"
|
"github.com/ory/fosite/compose"
|
||||||
|
|
||||||
@ -84,7 +85,7 @@ func PinnipedCLIOIDCClient() *fosite.DefaultOpenIDConnectClient {
|
|||||||
RedirectURIs: []string{"http://127.0.0.1/callback"},
|
RedirectURIs: []string{"http://127.0.0.1/callback"},
|
||||||
ResponseTypes: []string{"code"},
|
ResponseTypes: []string{"code"},
|
||||||
GrantTypes: []string{"authorization_code"},
|
GrantTypes: []string{"authorization_code"},
|
||||||
Scopes: []string{"openid", "profile", "email"},
|
Scopes: []string{coreosoidc.ScopeOpenID, coreosoidc.ScopeOfflineAccess, "profile", "email"},
|
||||||
},
|
},
|
||||||
TokenEndpointAuthMethod: "none",
|
TokenEndpointAuthMethod: "none",
|
||||||
}
|
}
|
||||||
@ -156,3 +157,11 @@ func FositeErrorForLog(err error) []interface{} {
|
|||||||
type IDPListGetter interface {
|
type IDPListGetter interface {
|
||||||
GetIDPList() []provider.UpstreamOIDCIdentityProviderI
|
GetIDPList() []provider.UpstreamOIDCIdentityProviderI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GrantScopeIfRequested(authorizeRequester fosite.AuthorizeRequester, scopeName string) {
|
||||||
|
for _, scope := range authorizeRequester.GetRequestedScopes() {
|
||||||
|
if scope == scopeName {
|
||||||
|
authorizeRequester.GrantScope(scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user