Revert adding allowAccessTokenBasedRefresh flag to OIDCIdentityProvider

Signed-off-by: Margo Crawford <margaretc@vmware.com>
This commit is contained in:
Ryan Richard 2022-01-10 17:03:31 -08:00 committed by Margo Crawford
parent 683a2c5b23
commit 91924ec685
25 changed files with 147 additions and 261 deletions

View File

@ -111,13 +111,6 @@ type OIDCAuthorizationConfig struct {
// allowPasswordGrant defaults to false. // allowPasswordGrant defaults to false.
// +optional // +optional
AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"` AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"`
// allowAccessTokenBasedRefresh, when true, will allow a user to refresh their tokens by checking their upstream access
// token against the user info endpoint, but skipping the refresh token flow. If it is possible to acquire a refresh token
// from your identity provider, you should do so. But if you can't, this option allows the refresh flow to work. We recommend
// updating the access token lifetime in your identity provider to at least an hour, or up to 9 hours long. Users session lengths
// will be tied to this access token lifetime.
AllowAccessTokenBasedRefresh bool `json:"allowAccessTokenBasedRefresh,omitempty"`
} }
// Parameter is a key/value pair which represents a parameter in an HTTP request. // Parameter is a key/value pair which represents a parameter in an HTTP request.

View File

@ -151,17 +151,6 @@ spec:
items: items:
type: string type: string
type: array type: array
allowAccessTokenBasedRefresh:
description: allowAccessTokenBasedRefresh, when true, will allow
a user to refresh their tokens by checking their upstream access
token against the user info endpoint, but skipping the refresh
token flow. If it is possible to acquire a refresh token from
your identity provider, you should do so. But if you can't,
this option allows the refresh flow to work. We recommend updating
the access token lifetime in your identity provider to at least
an hour, or up to 9 hours long. Users session lengths will be
tied to this access token lifetime.
type: boolean
allowPasswordGrant: allowPasswordGrant:
description: allowPasswordGrant, when true, will allow the use description: allowPasswordGrant, when true, will allow the use
of OAuth 2.0's Resource Owner Password Credentials Grant (see of OAuth 2.0's Resource Owner Password Credentials Grant (see

View File

@ -1102,7 +1102,6 @@ OIDCAuthorizationConfig provides information about how to form the OAuth2 author
| *`additionalScopes`* __string array__ | additionalScopes are the additional scopes that will be requested from your OIDC provider in the authorization request during an OIDC Authorization Code Flow and in the token request during a Resource Owner Password Credentials Grant. Note that the "openid" scope will always be requested regardless of the value in this setting, since it is always required according to the OIDC spec. By default, when this field is not set, the Supervisor will request the following scopes: "openid", "offline_access", "email", and "profile". See https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims for a description of the "profile" and "email" scopes. See https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess for a description of the "offline_access" scope. This default value may change in future versions of Pinniped as the standard evolves, or as common patterns used by providers who implement the standard in the ecosystem evolve. By setting this list to anything other than an empty list, you are overriding the default value, so you may wish to include some of "offline_access", "email", and "profile" in your override list. If you do not want any of these scopes to be requested, you may set this list to contain only "openid". Some OIDC providers may also require a scope to get access to the user's group membership, in which case you may wish to include it in this list. Sometimes the scope to request the user's group membership is called "groups", but unfortunately this is not specified in the OIDC standard. Generally speaking, you should include any scopes required to cause the appropriate claims to be the returned by your OIDC provider in the ID token or userinfo endpoint results for those claims which you would like to use in the oidcClaims settings to determine the usernames and group memberships of your Kubernetes users. See your OIDC provider's documentation for more information about what scopes are available to request claims. Additionally, the Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from these authorization flows. For most OIDC providers, the scope required to receive refresh tokens will be "offline_access". See the documentation of your OIDC provider's authorization and token endpoints for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. Note that it may be safe to send "offline_access" even to providers which do not require it, since the provider may ignore scopes that it does not understand or require (see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3). In the unusual case that you must avoid sending the "offline_access" scope, then you must override the default value of this setting. This is required if your OIDC provider will reject the request when it includes "offline_access" (e.g. GitLab's OIDC provider). | *`additionalScopes`* __string array__ | additionalScopes are the additional scopes that will be requested from your OIDC provider in the authorization request during an OIDC Authorization Code Flow and in the token request during a Resource Owner Password Credentials Grant. Note that the "openid" scope will always be requested regardless of the value in this setting, since it is always required according to the OIDC spec. By default, when this field is not set, the Supervisor will request the following scopes: "openid", "offline_access", "email", and "profile". See https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims for a description of the "profile" and "email" scopes. See https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess for a description of the "offline_access" scope. This default value may change in future versions of Pinniped as the standard evolves, or as common patterns used by providers who implement the standard in the ecosystem evolve. By setting this list to anything other than an empty list, you are overriding the default value, so you may wish to include some of "offline_access", "email", and "profile" in your override list. If you do not want any of these scopes to be requested, you may set this list to contain only "openid". Some OIDC providers may also require a scope to get access to the user's group membership, in which case you may wish to include it in this list. Sometimes the scope to request the user's group membership is called "groups", but unfortunately this is not specified in the OIDC standard. Generally speaking, you should include any scopes required to cause the appropriate claims to be the returned by your OIDC provider in the ID token or userinfo endpoint results for those claims which you would like to use in the oidcClaims settings to determine the usernames and group memberships of your Kubernetes users. See your OIDC provider's documentation for more information about what scopes are available to request claims. Additionally, the Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from these authorization flows. For most OIDC providers, the scope required to receive refresh tokens will be "offline_access". See the documentation of your OIDC provider's authorization and token endpoints for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. Note that it may be safe to send "offline_access" even to providers which do not require it, since the provider may ignore scopes that it does not understand or require (see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3). In the unusual case that you must avoid sending the "offline_access" scope, then you must override the default value of this setting. This is required if your OIDC provider will reject the request when it includes "offline_access" (e.g. GitLab's OIDC provider).
| *`additionalAuthorizeParameters`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-parameter[$$Parameter$$] array__ | additionalAuthorizeParameters are extra query parameters that should be included in the authorize request to your OIDC provider in the authorization request during an OIDC Authorization Code Flow. By default, no extra parameters are sent. The standard parameters that will be sent are "response_type", "scope", "client_id", "state", "nonce", "code_challenge", "code_challenge_method", and "redirect_uri". These parameters cannot be included in this setting. Additionally, the "hd" parameter cannot be included in this setting at this time. The "hd" parameter is used by Google's OIDC provider to provide a hint as to which "hosted domain" the user should use during login. However, Pinniped does not yet support validating the hosted domain in the resulting ID token, so it is not yet safe to use this feature of Google's OIDC provider with Pinniped. This setting does not influence the parameters sent to the token endpoint in the Resource Owner Password Credentials Grant. The Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from the authorization flows. Some OIDC providers may require a certain value for the "prompt" parameter in order to properly request refresh tokens. See the documentation of your OIDC provider's authorization endpoint for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. If your provider requires the prompt parameter to request a refresh token, then include it here. Also note that most providers also require a certain scope to be requested in order to receive refresh tokens. See the additionalScopes setting for more information about using scopes to request refresh tokens. | *`additionalAuthorizeParameters`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-parameter[$$Parameter$$] array__ | additionalAuthorizeParameters are extra query parameters that should be included in the authorize request to your OIDC provider in the authorization request during an OIDC Authorization Code Flow. By default, no extra parameters are sent. The standard parameters that will be sent are "response_type", "scope", "client_id", "state", "nonce", "code_challenge", "code_challenge_method", and "redirect_uri". These parameters cannot be included in this setting. Additionally, the "hd" parameter cannot be included in this setting at this time. The "hd" parameter is used by Google's OIDC provider to provide a hint as to which "hosted domain" the user should use during login. However, Pinniped does not yet support validating the hosted domain in the resulting ID token, so it is not yet safe to use this feature of Google's OIDC provider with Pinniped. This setting does not influence the parameters sent to the token endpoint in the Resource Owner Password Credentials Grant. The Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from the authorization flows. Some OIDC providers may require a certain value for the "prompt" parameter in order to properly request refresh tokens. See the documentation of your OIDC provider's authorization endpoint for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. If your provider requires the prompt parameter to request a refresh token, then include it here. Also note that most providers also require a certain scope to be requested in order to receive refresh tokens. See the additionalScopes setting for more information about using scopes to request refresh tokens.
| *`allowPasswordGrant`* __boolean__ | allowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant (see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow. The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be convenient for users, especially for identities from your OIDC provider which are not intended to represent a human actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it, you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords (similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins. allowPasswordGrant defaults to false. | *`allowPasswordGrant`* __boolean__ | allowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant (see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow. The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be convenient for users, especially for identities from your OIDC provider which are not intended to represent a human actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it, you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords (similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins. allowPasswordGrant defaults to false.
| *`allowAccessTokenBasedRefresh`* __boolean__ | allowAccessTokenBasedRefresh, when true, will allow a user to refresh their tokens by checking their upstream access token against the user info endpoint, but skipping the refresh token flow. If it is possible to acquire a refresh token from your identity provider, you should do so. But if you can't, this option allows the refresh flow to work. We recommend updating the access token lifetime in your identity provider to at least an hour, or up to 9 hours long. Users session lengths will be tied to this access token lifetime.
|=== |===

View File

@ -111,13 +111,6 @@ type OIDCAuthorizationConfig struct {
// allowPasswordGrant defaults to false. // allowPasswordGrant defaults to false.
// +optional // +optional
AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"` AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"`
// allowAccessTokenBasedRefresh, when true, will allow a user to refresh their tokens by checking their upstream access
// token against the user info endpoint, but skipping the refresh token flow. If it is possible to acquire a refresh token
// from your identity provider, you should do so. But if you can't, this option allows the refresh flow to work. We recommend
// updating the access token lifetime in your identity provider to at least an hour, or up to 9 hours long. Users session lengths
// will be tied to this access token lifetime.
AllowAccessTokenBasedRefresh bool `json:"allowAccessTokenBasedRefresh,omitempty"`
} }
// Parameter is a key/value pair which represents a parameter in an HTTP request. // Parameter is a key/value pair which represents a parameter in an HTTP request.

View File

@ -151,17 +151,6 @@ spec:
items: items:
type: string type: string
type: array type: array
allowAccessTokenBasedRefresh:
description: allowAccessTokenBasedRefresh, when true, will allow
a user to refresh their tokens by checking their upstream access
token against the user info endpoint, but skipping the refresh
token flow. If it is possible to acquire a refresh token from
your identity provider, you should do so. But if you can't,
this option allows the refresh flow to work. We recommend updating
the access token lifetime in your identity provider to at least
an hour, or up to 9 hours long. Users session lengths will be
tied to this access token lifetime.
type: boolean
allowPasswordGrant: allowPasswordGrant:
description: allowPasswordGrant, when true, will allow the use description: allowPasswordGrant, when true, will allow the use
of OAuth 2.0's Resource Owner Password Credentials Grant (see of OAuth 2.0's Resource Owner Password Credentials Grant (see

View File

@ -1102,7 +1102,6 @@ OIDCAuthorizationConfig provides information about how to form the OAuth2 author
| *`additionalScopes`* __string array__ | additionalScopes are the additional scopes that will be requested from your OIDC provider in the authorization request during an OIDC Authorization Code Flow and in the token request during a Resource Owner Password Credentials Grant. Note that the "openid" scope will always be requested regardless of the value in this setting, since it is always required according to the OIDC spec. By default, when this field is not set, the Supervisor will request the following scopes: "openid", "offline_access", "email", and "profile". See https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims for a description of the "profile" and "email" scopes. See https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess for a description of the "offline_access" scope. This default value may change in future versions of Pinniped as the standard evolves, or as common patterns used by providers who implement the standard in the ecosystem evolve. By setting this list to anything other than an empty list, you are overriding the default value, so you may wish to include some of "offline_access", "email", and "profile" in your override list. If you do not want any of these scopes to be requested, you may set this list to contain only "openid". Some OIDC providers may also require a scope to get access to the user's group membership, in which case you may wish to include it in this list. Sometimes the scope to request the user's group membership is called "groups", but unfortunately this is not specified in the OIDC standard. Generally speaking, you should include any scopes required to cause the appropriate claims to be the returned by your OIDC provider in the ID token or userinfo endpoint results for those claims which you would like to use in the oidcClaims settings to determine the usernames and group memberships of your Kubernetes users. See your OIDC provider's documentation for more information about what scopes are available to request claims. Additionally, the Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from these authorization flows. For most OIDC providers, the scope required to receive refresh tokens will be "offline_access". See the documentation of your OIDC provider's authorization and token endpoints for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. Note that it may be safe to send "offline_access" even to providers which do not require it, since the provider may ignore scopes that it does not understand or require (see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3). In the unusual case that you must avoid sending the "offline_access" scope, then you must override the default value of this setting. This is required if your OIDC provider will reject the request when it includes "offline_access" (e.g. GitLab's OIDC provider). | *`additionalScopes`* __string array__ | additionalScopes are the additional scopes that will be requested from your OIDC provider in the authorization request during an OIDC Authorization Code Flow and in the token request during a Resource Owner Password Credentials Grant. Note that the "openid" scope will always be requested regardless of the value in this setting, since it is always required according to the OIDC spec. By default, when this field is not set, the Supervisor will request the following scopes: "openid", "offline_access", "email", and "profile". See https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims for a description of the "profile" and "email" scopes. See https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess for a description of the "offline_access" scope. This default value may change in future versions of Pinniped as the standard evolves, or as common patterns used by providers who implement the standard in the ecosystem evolve. By setting this list to anything other than an empty list, you are overriding the default value, so you may wish to include some of "offline_access", "email", and "profile" in your override list. If you do not want any of these scopes to be requested, you may set this list to contain only "openid". Some OIDC providers may also require a scope to get access to the user's group membership, in which case you may wish to include it in this list. Sometimes the scope to request the user's group membership is called "groups", but unfortunately this is not specified in the OIDC standard. Generally speaking, you should include any scopes required to cause the appropriate claims to be the returned by your OIDC provider in the ID token or userinfo endpoint results for those claims which you would like to use in the oidcClaims settings to determine the usernames and group memberships of your Kubernetes users. See your OIDC provider's documentation for more information about what scopes are available to request claims. Additionally, the Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from these authorization flows. For most OIDC providers, the scope required to receive refresh tokens will be "offline_access". See the documentation of your OIDC provider's authorization and token endpoints for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. Note that it may be safe to send "offline_access" even to providers which do not require it, since the provider may ignore scopes that it does not understand or require (see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3). In the unusual case that you must avoid sending the "offline_access" scope, then you must override the default value of this setting. This is required if your OIDC provider will reject the request when it includes "offline_access" (e.g. GitLab's OIDC provider).
| *`additionalAuthorizeParameters`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-parameter[$$Parameter$$] array__ | additionalAuthorizeParameters are extra query parameters that should be included in the authorize request to your OIDC provider in the authorization request during an OIDC Authorization Code Flow. By default, no extra parameters are sent. The standard parameters that will be sent are "response_type", "scope", "client_id", "state", "nonce", "code_challenge", "code_challenge_method", and "redirect_uri". These parameters cannot be included in this setting. Additionally, the "hd" parameter cannot be included in this setting at this time. The "hd" parameter is used by Google's OIDC provider to provide a hint as to which "hosted domain" the user should use during login. However, Pinniped does not yet support validating the hosted domain in the resulting ID token, so it is not yet safe to use this feature of Google's OIDC provider with Pinniped. This setting does not influence the parameters sent to the token endpoint in the Resource Owner Password Credentials Grant. The Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from the authorization flows. Some OIDC providers may require a certain value for the "prompt" parameter in order to properly request refresh tokens. See the documentation of your OIDC provider's authorization endpoint for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. If your provider requires the prompt parameter to request a refresh token, then include it here. Also note that most providers also require a certain scope to be requested in order to receive refresh tokens. See the additionalScopes setting for more information about using scopes to request refresh tokens. | *`additionalAuthorizeParameters`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-parameter[$$Parameter$$] array__ | additionalAuthorizeParameters are extra query parameters that should be included in the authorize request to your OIDC provider in the authorization request during an OIDC Authorization Code Flow. By default, no extra parameters are sent. The standard parameters that will be sent are "response_type", "scope", "client_id", "state", "nonce", "code_challenge", "code_challenge_method", and "redirect_uri". These parameters cannot be included in this setting. Additionally, the "hd" parameter cannot be included in this setting at this time. The "hd" parameter is used by Google's OIDC provider to provide a hint as to which "hosted domain" the user should use during login. However, Pinniped does not yet support validating the hosted domain in the resulting ID token, so it is not yet safe to use this feature of Google's OIDC provider with Pinniped. This setting does not influence the parameters sent to the token endpoint in the Resource Owner Password Credentials Grant. The Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from the authorization flows. Some OIDC providers may require a certain value for the "prompt" parameter in order to properly request refresh tokens. See the documentation of your OIDC provider's authorization endpoint for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. If your provider requires the prompt parameter to request a refresh token, then include it here. Also note that most providers also require a certain scope to be requested in order to receive refresh tokens. See the additionalScopes setting for more information about using scopes to request refresh tokens.
| *`allowPasswordGrant`* __boolean__ | allowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant (see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow. The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be convenient for users, especially for identities from your OIDC provider which are not intended to represent a human actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it, you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords (similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins. allowPasswordGrant defaults to false. | *`allowPasswordGrant`* __boolean__ | allowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant (see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow. The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be convenient for users, especially for identities from your OIDC provider which are not intended to represent a human actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it, you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords (similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins. allowPasswordGrant defaults to false.
| *`allowAccessTokenBasedRefresh`* __boolean__ | allowAccessTokenBasedRefresh, when true, will allow a user to refresh their tokens by checking their upstream access token against the user info endpoint, but skipping the refresh token flow. If it is possible to acquire a refresh token from your identity provider, you should do so. But if you can't, this option allows the refresh flow to work. We recommend updating the access token lifetime in your identity provider to at least an hour, or up to 9 hours long. Users session lengths will be tied to this access token lifetime.
|=== |===

View File

@ -111,13 +111,6 @@ type OIDCAuthorizationConfig struct {
// allowPasswordGrant defaults to false. // allowPasswordGrant defaults to false.
// +optional // +optional
AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"` AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"`
// allowAccessTokenBasedRefresh, when true, will allow a user to refresh their tokens by checking their upstream access
// token against the user info endpoint, but skipping the refresh token flow. If it is possible to acquire a refresh token
// from your identity provider, you should do so. But if you can't, this option allows the refresh flow to work. We recommend
// updating the access token lifetime in your identity provider to at least an hour, or up to 9 hours long. Users session lengths
// will be tied to this access token lifetime.
AllowAccessTokenBasedRefresh bool `json:"allowAccessTokenBasedRefresh,omitempty"`
} }
// Parameter is a key/value pair which represents a parameter in an HTTP request. // Parameter is a key/value pair which represents a parameter in an HTTP request.

View File

@ -151,17 +151,6 @@ spec:
items: items:
type: string type: string
type: array type: array
allowAccessTokenBasedRefresh:
description: allowAccessTokenBasedRefresh, when true, will allow
a user to refresh their tokens by checking their upstream access
token against the user info endpoint, but skipping the refresh
token flow. If it is possible to acquire a refresh token from
your identity provider, you should do so. But if you can't,
this option allows the refresh flow to work. We recommend updating
the access token lifetime in your identity provider to at least
an hour, or up to 9 hours long. Users session lengths will be
tied to this access token lifetime.
type: boolean
allowPasswordGrant: allowPasswordGrant:
description: allowPasswordGrant, when true, will allow the use description: allowPasswordGrant, when true, will allow the use
of OAuth 2.0's Resource Owner Password Credentials Grant (see of OAuth 2.0's Resource Owner Password Credentials Grant (see

View File

@ -1102,7 +1102,6 @@ OIDCAuthorizationConfig provides information about how to form the OAuth2 author
| *`additionalScopes`* __string array__ | additionalScopes are the additional scopes that will be requested from your OIDC provider in the authorization request during an OIDC Authorization Code Flow and in the token request during a Resource Owner Password Credentials Grant. Note that the "openid" scope will always be requested regardless of the value in this setting, since it is always required according to the OIDC spec. By default, when this field is not set, the Supervisor will request the following scopes: "openid", "offline_access", "email", and "profile". See https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims for a description of the "profile" and "email" scopes. See https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess for a description of the "offline_access" scope. This default value may change in future versions of Pinniped as the standard evolves, or as common patterns used by providers who implement the standard in the ecosystem evolve. By setting this list to anything other than an empty list, you are overriding the default value, so you may wish to include some of "offline_access", "email", and "profile" in your override list. If you do not want any of these scopes to be requested, you may set this list to contain only "openid". Some OIDC providers may also require a scope to get access to the user's group membership, in which case you may wish to include it in this list. Sometimes the scope to request the user's group membership is called "groups", but unfortunately this is not specified in the OIDC standard. Generally speaking, you should include any scopes required to cause the appropriate claims to be the returned by your OIDC provider in the ID token or userinfo endpoint results for those claims which you would like to use in the oidcClaims settings to determine the usernames and group memberships of your Kubernetes users. See your OIDC provider's documentation for more information about what scopes are available to request claims. Additionally, the Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from these authorization flows. For most OIDC providers, the scope required to receive refresh tokens will be "offline_access". See the documentation of your OIDC provider's authorization and token endpoints for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. Note that it may be safe to send "offline_access" even to providers which do not require it, since the provider may ignore scopes that it does not understand or require (see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3). In the unusual case that you must avoid sending the "offline_access" scope, then you must override the default value of this setting. This is required if your OIDC provider will reject the request when it includes "offline_access" (e.g. GitLab's OIDC provider). | *`additionalScopes`* __string array__ | additionalScopes are the additional scopes that will be requested from your OIDC provider in the authorization request during an OIDC Authorization Code Flow and in the token request during a Resource Owner Password Credentials Grant. Note that the "openid" scope will always be requested regardless of the value in this setting, since it is always required according to the OIDC spec. By default, when this field is not set, the Supervisor will request the following scopes: "openid", "offline_access", "email", and "profile". See https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims for a description of the "profile" and "email" scopes. See https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess for a description of the "offline_access" scope. This default value may change in future versions of Pinniped as the standard evolves, or as common patterns used by providers who implement the standard in the ecosystem evolve. By setting this list to anything other than an empty list, you are overriding the default value, so you may wish to include some of "offline_access", "email", and "profile" in your override list. If you do not want any of these scopes to be requested, you may set this list to contain only "openid". Some OIDC providers may also require a scope to get access to the user's group membership, in which case you may wish to include it in this list. Sometimes the scope to request the user's group membership is called "groups", but unfortunately this is not specified in the OIDC standard. Generally speaking, you should include any scopes required to cause the appropriate claims to be the returned by your OIDC provider in the ID token or userinfo endpoint results for those claims which you would like to use in the oidcClaims settings to determine the usernames and group memberships of your Kubernetes users. See your OIDC provider's documentation for more information about what scopes are available to request claims. Additionally, the Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from these authorization flows. For most OIDC providers, the scope required to receive refresh tokens will be "offline_access". See the documentation of your OIDC provider's authorization and token endpoints for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. Note that it may be safe to send "offline_access" even to providers which do not require it, since the provider may ignore scopes that it does not understand or require (see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3). In the unusual case that you must avoid sending the "offline_access" scope, then you must override the default value of this setting. This is required if your OIDC provider will reject the request when it includes "offline_access" (e.g. GitLab's OIDC provider).
| *`additionalAuthorizeParameters`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-parameter[$$Parameter$$] array__ | additionalAuthorizeParameters are extra query parameters that should be included in the authorize request to your OIDC provider in the authorization request during an OIDC Authorization Code Flow. By default, no extra parameters are sent. The standard parameters that will be sent are "response_type", "scope", "client_id", "state", "nonce", "code_challenge", "code_challenge_method", and "redirect_uri". These parameters cannot be included in this setting. Additionally, the "hd" parameter cannot be included in this setting at this time. The "hd" parameter is used by Google's OIDC provider to provide a hint as to which "hosted domain" the user should use during login. However, Pinniped does not yet support validating the hosted domain in the resulting ID token, so it is not yet safe to use this feature of Google's OIDC provider with Pinniped. This setting does not influence the parameters sent to the token endpoint in the Resource Owner Password Credentials Grant. The Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from the authorization flows. Some OIDC providers may require a certain value for the "prompt" parameter in order to properly request refresh tokens. See the documentation of your OIDC provider's authorization endpoint for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. If your provider requires the prompt parameter to request a refresh token, then include it here. Also note that most providers also require a certain scope to be requested in order to receive refresh tokens. See the additionalScopes setting for more information about using scopes to request refresh tokens. | *`additionalAuthorizeParameters`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-parameter[$$Parameter$$] array__ | additionalAuthorizeParameters are extra query parameters that should be included in the authorize request to your OIDC provider in the authorization request during an OIDC Authorization Code Flow. By default, no extra parameters are sent. The standard parameters that will be sent are "response_type", "scope", "client_id", "state", "nonce", "code_challenge", "code_challenge_method", and "redirect_uri". These parameters cannot be included in this setting. Additionally, the "hd" parameter cannot be included in this setting at this time. The "hd" parameter is used by Google's OIDC provider to provide a hint as to which "hosted domain" the user should use during login. However, Pinniped does not yet support validating the hosted domain in the resulting ID token, so it is not yet safe to use this feature of Google's OIDC provider with Pinniped. This setting does not influence the parameters sent to the token endpoint in the Resource Owner Password Credentials Grant. The Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from the authorization flows. Some OIDC providers may require a certain value for the "prompt" parameter in order to properly request refresh tokens. See the documentation of your OIDC provider's authorization endpoint for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. If your provider requires the prompt parameter to request a refresh token, then include it here. Also note that most providers also require a certain scope to be requested in order to receive refresh tokens. See the additionalScopes setting for more information about using scopes to request refresh tokens.
| *`allowPasswordGrant`* __boolean__ | allowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant (see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow. The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be convenient for users, especially for identities from your OIDC provider which are not intended to represent a human actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it, you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords (similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins. allowPasswordGrant defaults to false. | *`allowPasswordGrant`* __boolean__ | allowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant (see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow. The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be convenient for users, especially for identities from your OIDC provider which are not intended to represent a human actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it, you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords (similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins. allowPasswordGrant defaults to false.
| *`allowAccessTokenBasedRefresh`* __boolean__ | allowAccessTokenBasedRefresh, when true, will allow a user to refresh their tokens by checking their upstream access token against the user info endpoint, but skipping the refresh token flow. If it is possible to acquire a refresh token from your identity provider, you should do so. But if you can't, this option allows the refresh flow to work. We recommend updating the access token lifetime in your identity provider to at least an hour, or up to 9 hours long. Users session lengths will be tied to this access token lifetime.
|=== |===

View File

@ -111,13 +111,6 @@ type OIDCAuthorizationConfig struct {
// allowPasswordGrant defaults to false. // allowPasswordGrant defaults to false.
// +optional // +optional
AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"` AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"`
// allowAccessTokenBasedRefresh, when true, will allow a user to refresh their tokens by checking their upstream access
// token against the user info endpoint, but skipping the refresh token flow. If it is possible to acquire a refresh token
// from your identity provider, you should do so. But if you can't, this option allows the refresh flow to work. We recommend
// updating the access token lifetime in your identity provider to at least an hour, or up to 9 hours long. Users session lengths
// will be tied to this access token lifetime.
AllowAccessTokenBasedRefresh bool `json:"allowAccessTokenBasedRefresh,omitempty"`
} }
// Parameter is a key/value pair which represents a parameter in an HTTP request. // Parameter is a key/value pair which represents a parameter in an HTTP request.

View File

@ -151,17 +151,6 @@ spec:
items: items:
type: string type: string
type: array type: array
allowAccessTokenBasedRefresh:
description: allowAccessTokenBasedRefresh, when true, will allow
a user to refresh their tokens by checking their upstream access
token against the user info endpoint, but skipping the refresh
token flow. If it is possible to acquire a refresh token from
your identity provider, you should do so. But if you can't,
this option allows the refresh flow to work. We recommend updating
the access token lifetime in your identity provider to at least
an hour, or up to 9 hours long. Users session lengths will be
tied to this access token lifetime.
type: boolean
allowPasswordGrant: allowPasswordGrant:
description: allowPasswordGrant, when true, will allow the use description: allowPasswordGrant, when true, will allow the use
of OAuth 2.0's Resource Owner Password Credentials Grant (see of OAuth 2.0's Resource Owner Password Credentials Grant (see

View File

@ -1102,7 +1102,6 @@ OIDCAuthorizationConfig provides information about how to form the OAuth2 author
| *`additionalScopes`* __string array__ | additionalScopes are the additional scopes that will be requested from your OIDC provider in the authorization request during an OIDC Authorization Code Flow and in the token request during a Resource Owner Password Credentials Grant. Note that the "openid" scope will always be requested regardless of the value in this setting, since it is always required according to the OIDC spec. By default, when this field is not set, the Supervisor will request the following scopes: "openid", "offline_access", "email", and "profile". See https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims for a description of the "profile" and "email" scopes. See https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess for a description of the "offline_access" scope. This default value may change in future versions of Pinniped as the standard evolves, or as common patterns used by providers who implement the standard in the ecosystem evolve. By setting this list to anything other than an empty list, you are overriding the default value, so you may wish to include some of "offline_access", "email", and "profile" in your override list. If you do not want any of these scopes to be requested, you may set this list to contain only "openid". Some OIDC providers may also require a scope to get access to the user's group membership, in which case you may wish to include it in this list. Sometimes the scope to request the user's group membership is called "groups", but unfortunately this is not specified in the OIDC standard. Generally speaking, you should include any scopes required to cause the appropriate claims to be the returned by your OIDC provider in the ID token or userinfo endpoint results for those claims which you would like to use in the oidcClaims settings to determine the usernames and group memberships of your Kubernetes users. See your OIDC provider's documentation for more information about what scopes are available to request claims. Additionally, the Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from these authorization flows. For most OIDC providers, the scope required to receive refresh tokens will be "offline_access". See the documentation of your OIDC provider's authorization and token endpoints for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. Note that it may be safe to send "offline_access" even to providers which do not require it, since the provider may ignore scopes that it does not understand or require (see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3). In the unusual case that you must avoid sending the "offline_access" scope, then you must override the default value of this setting. This is required if your OIDC provider will reject the request when it includes "offline_access" (e.g. GitLab's OIDC provider). | *`additionalScopes`* __string array__ | additionalScopes are the additional scopes that will be requested from your OIDC provider in the authorization request during an OIDC Authorization Code Flow and in the token request during a Resource Owner Password Credentials Grant. Note that the "openid" scope will always be requested regardless of the value in this setting, since it is always required according to the OIDC spec. By default, when this field is not set, the Supervisor will request the following scopes: "openid", "offline_access", "email", and "profile". See https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims for a description of the "profile" and "email" scopes. See https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess for a description of the "offline_access" scope. This default value may change in future versions of Pinniped as the standard evolves, or as common patterns used by providers who implement the standard in the ecosystem evolve. By setting this list to anything other than an empty list, you are overriding the default value, so you may wish to include some of "offline_access", "email", and "profile" in your override list. If you do not want any of these scopes to be requested, you may set this list to contain only "openid". Some OIDC providers may also require a scope to get access to the user's group membership, in which case you may wish to include it in this list. Sometimes the scope to request the user's group membership is called "groups", but unfortunately this is not specified in the OIDC standard. Generally speaking, you should include any scopes required to cause the appropriate claims to be the returned by your OIDC provider in the ID token or userinfo endpoint results for those claims which you would like to use in the oidcClaims settings to determine the usernames and group memberships of your Kubernetes users. See your OIDC provider's documentation for more information about what scopes are available to request claims. Additionally, the Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from these authorization flows. For most OIDC providers, the scope required to receive refresh tokens will be "offline_access". See the documentation of your OIDC provider's authorization and token endpoints for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. Note that it may be safe to send "offline_access" even to providers which do not require it, since the provider may ignore scopes that it does not understand or require (see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3). In the unusual case that you must avoid sending the "offline_access" scope, then you must override the default value of this setting. This is required if your OIDC provider will reject the request when it includes "offline_access" (e.g. GitLab's OIDC provider).
| *`additionalAuthorizeParameters`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-parameter[$$Parameter$$] array__ | additionalAuthorizeParameters are extra query parameters that should be included in the authorize request to your OIDC provider in the authorization request during an OIDC Authorization Code Flow. By default, no extra parameters are sent. The standard parameters that will be sent are "response_type", "scope", "client_id", "state", "nonce", "code_challenge", "code_challenge_method", and "redirect_uri". These parameters cannot be included in this setting. Additionally, the "hd" parameter cannot be included in this setting at this time. The "hd" parameter is used by Google's OIDC provider to provide a hint as to which "hosted domain" the user should use during login. However, Pinniped does not yet support validating the hosted domain in the resulting ID token, so it is not yet safe to use this feature of Google's OIDC provider with Pinniped. This setting does not influence the parameters sent to the token endpoint in the Resource Owner Password Credentials Grant. The Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from the authorization flows. Some OIDC providers may require a certain value for the "prompt" parameter in order to properly request refresh tokens. See the documentation of your OIDC provider's authorization endpoint for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. If your provider requires the prompt parameter to request a refresh token, then include it here. Also note that most providers also require a certain scope to be requested in order to receive refresh tokens. See the additionalScopes setting for more information about using scopes to request refresh tokens. | *`additionalAuthorizeParameters`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-parameter[$$Parameter$$] array__ | additionalAuthorizeParameters are extra query parameters that should be included in the authorize request to your OIDC provider in the authorization request during an OIDC Authorization Code Flow. By default, no extra parameters are sent. The standard parameters that will be sent are "response_type", "scope", "client_id", "state", "nonce", "code_challenge", "code_challenge_method", and "redirect_uri". These parameters cannot be included in this setting. Additionally, the "hd" parameter cannot be included in this setting at this time. The "hd" parameter is used by Google's OIDC provider to provide a hint as to which "hosted domain" the user should use during login. However, Pinniped does not yet support validating the hosted domain in the resulting ID token, so it is not yet safe to use this feature of Google's OIDC provider with Pinniped. This setting does not influence the parameters sent to the token endpoint in the Resource Owner Password Credentials Grant. The Pinniped Supervisor requires that your OIDC provider returns refresh tokens to the Supervisor from the authorization flows. Some OIDC providers may require a certain value for the "prompt" parameter in order to properly request refresh tokens. See the documentation of your OIDC provider's authorization endpoint for its requirements for what to include in the request in order to receive a refresh token in the response, if anything. If your provider requires the prompt parameter to request a refresh token, then include it here. Also note that most providers also require a certain scope to be requested in order to receive refresh tokens. See the additionalScopes setting for more information about using scopes to request refresh tokens.
| *`allowPasswordGrant`* __boolean__ | allowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant (see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow. The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be convenient for users, especially for identities from your OIDC provider which are not intended to represent a human actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it, you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords (similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins. allowPasswordGrant defaults to false. | *`allowPasswordGrant`* __boolean__ | allowPasswordGrant, when true, will allow the use of OAuth 2.0's Resource Owner Password Credentials Grant (see https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to authenticate to the OIDC provider using a username and password without a web browser, in addition to the usual browser-based OIDC Authorization Code Flow. The Resource Owner Password Credentials Grant is not officially part of the OIDC specification, so it may not be supported by your OIDC provider. If your OIDC provider supports returning ID tokens from a Resource Owner Password Credentials Grant token request, then you can choose to set this field to true. This will allow end users to choose to present their username and password to the kubectl CLI (using the Pinniped plugin) to authenticate to the cluster, without using a web browser to log in as is customary in OIDC Authorization Code Flow. This may be convenient for users, especially for identities from your OIDC provider which are not intended to represent a human actor, such as service accounts performing actions in a CI/CD environment. Even if your OIDC provider supports it, you may wish to disable this behavior by setting this field to false when you prefer to only allow users of this OIDCIdentityProvider to log in via the browser-based OIDC Authorization Code Flow. Using the Resource Owner Password Credentials Grant means that the Pinniped CLI and Pinniped Supervisor will directly handle your end users' passwords (similar to LDAPIdentityProvider), and you will not be able to require multi-factor authentication or use the other web-based login features of your OIDC provider during Resource Owner Password Credentials Grant logins. allowPasswordGrant defaults to false.
| *`allowAccessTokenBasedRefresh`* __boolean__ | allowAccessTokenBasedRefresh, when true, will allow a user to refresh their tokens by checking their upstream access token against the user info endpoint, but skipping the refresh token flow. If it is possible to acquire a refresh token from your identity provider, you should do so. But if you can't, this option allows the refresh flow to work. We recommend updating the access token lifetime in your identity provider to at least an hour, or up to 9 hours long. Users session lengths will be tied to this access token lifetime.
|=== |===

View File

@ -111,13 +111,6 @@ type OIDCAuthorizationConfig struct {
// allowPasswordGrant defaults to false. // allowPasswordGrant defaults to false.
// +optional // +optional
AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"` AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"`
// allowAccessTokenBasedRefresh, when true, will allow a user to refresh their tokens by checking their upstream access
// token against the user info endpoint, but skipping the refresh token flow. If it is possible to acquire a refresh token
// from your identity provider, you should do so. But if you can't, this option allows the refresh flow to work. We recommend
// updating the access token lifetime in your identity provider to at least an hour, or up to 9 hours long. Users session lengths
// will be tied to this access token lifetime.
AllowAccessTokenBasedRefresh bool `json:"allowAccessTokenBasedRefresh,omitempty"`
} }
// Parameter is a key/value pair which represents a parameter in an HTTP request. // Parameter is a key/value pair which represents a parameter in an HTTP request.

View File

@ -151,17 +151,6 @@ spec:
items: items:
type: string type: string
type: array type: array
allowAccessTokenBasedRefresh:
description: allowAccessTokenBasedRefresh, when true, will allow
a user to refresh their tokens by checking their upstream access
token against the user info endpoint, but skipping the refresh
token flow. If it is possible to acquire a refresh token from
your identity provider, you should do so. But if you can't,
this option allows the refresh flow to work. We recommend updating
the access token lifetime in your identity provider to at least
an hour, or up to 9 hours long. Users session lengths will be
tied to this access token lifetime.
type: boolean
allowPasswordGrant: allowPasswordGrant:
description: allowPasswordGrant, when true, will allow the use description: allowPasswordGrant, when true, will allow the use
of OAuth 2.0's Resource Owner Password Credentials Grant (see of OAuth 2.0's Resource Owner Password Credentials Grant (see

View File

@ -111,13 +111,6 @@ type OIDCAuthorizationConfig struct {
// allowPasswordGrant defaults to false. // allowPasswordGrant defaults to false.
// +optional // +optional
AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"` AllowPasswordGrant bool `json:"allowPasswordGrant,omitempty"`
// allowAccessTokenBasedRefresh, when true, will allow a user to refresh their tokens by checking their upstream access
// token against the user info endpoint, but skipping the refresh token flow. If it is possible to acquire a refresh token
// from your identity provider, you should do so. But if you can't, this option allows the refresh flow to work. We recommend
// updating the access token lifetime in your identity provider to at least an hour, or up to 9 hours long. Users session lengths
// will be tied to this access token lifetime.
AllowAccessTokenBasedRefresh bool `json:"allowAccessTokenBasedRefresh,omitempty"`
} }
// Parameter is a key/value pair which represents a parameter in an HTTP request. // Parameter is a key/value pair which represents a parameter in an HTTP request.

View File

@ -210,12 +210,11 @@ func (c *oidcWatcherController) validateUpstream(ctx controllerlib.Context, upst
Config: &oauth2.Config{ Config: &oauth2.Config{
Scopes: computeScopes(authorizationConfig.AdditionalScopes), Scopes: computeScopes(authorizationConfig.AdditionalScopes),
}, },
UsernameClaim: upstream.Spec.Claims.Username, UsernameClaim: upstream.Spec.Claims.Username,
GroupsClaim: upstream.Spec.Claims.Groups, GroupsClaim: upstream.Spec.Claims.Groups,
AllowPasswordGrant: authorizationConfig.AllowPasswordGrant, AllowPasswordGrant: authorizationConfig.AllowPasswordGrant,
AllowAccessTokenBasedRefresh: authorizationConfig.AllowAccessTokenBasedRefresh, AdditionalAuthcodeParams: additionalAuthcodeAuthorizeParameters,
AdditionalAuthcodeParams: additionalAuthcodeAuthorizeParameters, ResourceUID: upstream.UID,
ResourceUID: upstream.UID,
} }
conditions := []*v1alpha1.Condition{ conditions := []*v1alpha1.Condition{

View File

@ -45,20 +45,6 @@ func (m *MockUpstreamOIDCIdentityProviderI) EXPECT() *MockUpstreamOIDCIdentityPr
return m.recorder return m.recorder
} }
// AllowsAccessTokenBasedRefresh mocks base method.
func (m *MockUpstreamOIDCIdentityProviderI) AllowsAccessTokenBasedRefresh() bool {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AllowsAccessTokenBasedRefresh")
ret0, _ := ret[0].(bool)
return ret0
}
// AllowsAccessTokenBasedRefresh indicates an expected call of AllowsAccessTokenBasedRefresh.
func (mr *MockUpstreamOIDCIdentityProviderIMockRecorder) AllowsAccessTokenBasedRefresh() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllowsAccessTokenBasedRefresh", reflect.TypeOf((*MockUpstreamOIDCIdentityProviderI)(nil).AllowsAccessTokenBasedRefresh))
}
// AllowsPasswordGrant mocks base method. // AllowsPasswordGrant mocks base method.
func (m *MockUpstreamOIDCIdentityProviderI) AllowsPasswordGrant() bool { func (m *MockUpstreamOIDCIdentityProviderI) AllowsPasswordGrant() bool {
m.ctrl.T.Helper() m.ctrl.T.Helper()

View File

@ -174,17 +174,6 @@ func handleAuthRequestForOIDCUpstreamPasswordGrant(
fosite.ErrAccessDenied.WithDebug(err.Error()), true) // WithDebug hides the error from the client fosite.ErrAccessDenied.WithDebug(err.Error()), true) // WithDebug hides the error from the client
} }
if token.RefreshToken == nil || token.RefreshToken.Token == "" && !oidcUpstream.AllowsAccessTokenBasedRefresh() {
// TODO change warning message
plog.Warning("refresh token not returned by upstream provider during password grant, "+
"please check configuration of OIDCIdentityProvider and the client in the upstream provider's API/UI",
"upstreamName", oidcUpstream.GetName(),
"scopes", oidcUpstream.GetScopes())
return writeAuthorizeError(w, oauthHelper, authorizeRequester,
fosite.ErrAccessDenied.WithHint(
"Refresh token not returned by upstream provider during password grant."), true)
}
subject, username, groups, err := downstreamsession.GetDownstreamIdentityFromUpstreamIDToken(oidcUpstream, token.IDToken.Claims) subject, username, groups, err := downstreamsession.GetDownstreamIdentityFromUpstreamIDToken(oidcUpstream, token.IDToken.Claims)
if err != nil { if err != nil {
// Return a user-friendly error for this case which is entirely within our control. // Return a user-friendly error for this case which is entirely within our control.
@ -212,22 +201,33 @@ func handleAuthRequestForOIDCUpstreamPasswordGrant(
ProviderName: oidcUpstream.GetName(), ProviderName: oidcUpstream.GetName(),
ProviderType: psession.ProviderTypeOIDC, ProviderType: psession.ProviderTypeOIDC,
OIDC: &psession.OIDCSessionData{ OIDC: &psession.OIDCSessionData{
UpstreamRefreshToken: token.RefreshToken.Token, UpstreamIssuer: upstreamIssuer,
UpstreamIssuer: upstreamIssuer, UpstreamSubject: upstreamSubject,
UpstreamSubject: upstreamSubject,
}, },
} }
if token.RefreshToken == nil || token.RefreshToken.Token == "" { hasRefreshToken := token.RefreshToken != nil && token.RefreshToken.Token != ""
if token.AccessToken == nil || token.AccessToken.Token == "" { hasAccessToken := token.AccessToken != nil && token.AccessToken.Token != ""
return writeAuthorizeError(w, oauthHelper, authorizeRequester, switch {
fosite.ErrAccessDenied.WithHint( case hasRefreshToken: // we prefer refresh tokens, so check for this first
"Access token not returned by upstream provider during password grant."), true) customSessionData.OIDC.UpstreamRefreshToken = token.RefreshToken.Token
} case hasAccessToken:
customSessionData.OIDC = &psession.OIDCSessionData{ plog.Info("refresh token not returned by upstream provider during password grant, using access token instead. "+
UpstreamAccessToken: token.AccessToken.Token, "please check configuration of OIDCIdentityProvider and the client in the upstream provider's API/UI "+
} "and try to get a refresh token if possible",
"upstreamName", oidcUpstream.GetName(),
"scopes", oidcUpstream.GetScopes())
customSessionData.OIDC.UpstreamAccessToken = token.AccessToken.Token
default:
plog.Warning("refresh token and access token not returned by upstream provider during password grant, "+
"please check configuration of OIDCIdentityProvider and the client in the upstream provider's API/UI",
"upstreamName", oidcUpstream.GetName(),
"scopes", oidcUpstream.GetScopes())
return writeAuthorizeError(w, oauthHelper, authorizeRequester,
fosite.ErrAccessDenied.WithHint(
"Neither access token nor refresh token returned by upstream provider during password grant."), true)
} }
return makeDownstreamSessionAndReturnAuthcodeRedirect(r, w, oauthHelper, authorizeRequester, subject, username, groups, customSessionData) return makeDownstreamSessionAndReturnAuthcodeRedirect(r, w, oauthHelper, authorizeRequester, subject, username, groups, customSessionData)
} }

View File

@ -56,6 +56,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
oidcUpstreamUsernameClaim = "the-user-claim" oidcUpstreamUsernameClaim = "the-user-claim"
oidcUpstreamGroupsClaim = "the-groups-claim" oidcUpstreamGroupsClaim = "the-groups-claim"
oidcPasswordGrantUpstreamRefreshToken = "some-opaque-token" //nolint: gosec oidcPasswordGrantUpstreamRefreshToken = "some-opaque-token" //nolint: gosec
oidcUpstreamAccessToken = "some-access-token"
downstreamIssuer = "https://my-downstream-issuer.com/some-path" downstreamIssuer = "https://my-downstream-issuer.com/some-path"
downstreamRedirectURI = "http://127.0.0.1/callback" downstreamRedirectURI = "http://127.0.0.1/callback"
@ -154,15 +155,9 @@ func TestAuthorizationEndpoint(t *testing.T) {
"state": happyState, "state": happyState,
} }
fositeAccessDeniedWithMissingRefreshTokenErrorQuery = map[string]string{
"error": "access_denied",
"error_description": "The resource owner or authorization server denied the request. Refresh token not returned by upstream provider during password grant.",
"state": happyState,
}
fositeAccessDeniedWithMissingAccessTokenErrorQuery = map[string]string{ fositeAccessDeniedWithMissingAccessTokenErrorQuery = map[string]string{
"error": "access_denied", "error": "access_denied",
"error_description": "The resource owner or authorization server denied the request. Access token not returned by upstream provider during password grant.", "error_description": "The resource owner or authorization server denied the request. Neither access token nor refresh token returned by upstream provider during password grant.",
"state": happyState, "state": happyState,
} }
@ -486,7 +481,9 @@ func TestAuthorizationEndpoint(t *testing.T) {
ProviderName: oidcPasswordGrantUpstreamName, ProviderName: oidcPasswordGrantUpstreamName,
ProviderType: psession.ProviderTypeOIDC, ProviderType: psession.ProviderTypeOIDC,
OIDC: &psession.OIDCSessionData{ OIDC: &psession.OIDCSessionData{
UpstreamAccessToken: "some-access-token", UpstreamAccessToken: oidcUpstreamAccessToken,
UpstreamSubject: oidcUpstreamSubject,
UpstreamIssuer: oidcUpstreamIssuer,
}, },
} }
@ -889,8 +886,30 @@ func TestAuthorizationEndpoint(t *testing.T) {
wantBodyStringWithLocationInHref: true, wantBodyStringWithLocationInHref: true,
}, },
{ {
name: "doesn't return an error if allowAccessTokenRefresh is set when upstream IDP did not return a refresh token", name: "OIDC password grant happy path when upstream IDP returned empty refresh token but it did return an access token",
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithAllowAccessTokenBasedRefresh(true).WithEmptyRefreshToken().WithAccessToken("some-access-token").Build()), idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithEmptyRefreshToken().WithAccessToken(oidcUpstreamAccessToken).Build()),
method: http.MethodGet,
path: happyGetRequestPath,
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
wantStatus: http.StatusFound,
wantContentType: htmlContentType,
wantRedirectLocationRegexp: happyAuthcodeDownstreamRedirectLocationRegexp,
wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
wantDownstreamIDTokenGroups: oidcUpstreamGroupMembership,
wantDownstreamRequestedScopes: happyDownstreamScopesRequested,
wantDownstreamRedirectURI: downstreamRedirectURI,
wantDownstreamGrantedScopes: happyDownstreamScopesGranted,
wantDownstreamNonce: downstreamNonce,
wantDownstreamPKCEChallenge: downstreamPKCEChallenge,
wantDownstreamPKCEChallengeMethod: downstreamPKCEChallengeMethod,
wantDownstreamCustomSessionData: expectedHappyOIDCPasswordGrantCustomSessionWithAccessToken,
},
{
name: "OIDC password grant happy path when upstream IDP did not return a refresh token but it did return an access token",
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithoutRefreshToken().WithAccessToken(oidcUpstreamAccessToken).Build()),
method: http.MethodGet, method: http.MethodGet,
path: happyGetRequestPath, path: happyGetRequestPath,
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername), customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
@ -1052,34 +1071,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
wantBodyString: "", wantBodyString: "",
}, },
{ {
name: "return an error when upstream IDP did not return a refresh token", name: "return an error when upstream IDP returns empty refresh token and empty access token",
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithoutRefreshToken().Build()), idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithEmptyRefreshToken().WithEmptyAccessToken().Build()),
method: http.MethodGet,
path: happyGetRequestPath,
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
wantStatus: http.StatusFound,
wantContentType: "application/json; charset=utf-8",
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithMissingRefreshTokenErrorQuery),
wantBodyString: "",
},
{
name: "return an error when upstream IDP did not return a refresh token",
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithEmptyRefreshToken().Build()),
method: http.MethodGet,
path: happyGetRequestPath,
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
wantStatus: http.StatusFound,
wantContentType: "application/json; charset=utf-8",
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithMissingRefreshTokenErrorQuery),
wantBodyString: "",
},
{
name: "return an error when upstream IDP did not return an access or refresh token and allowAccessTokenBasedRefresh is true",
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithEmptyRefreshToken().WithAllowAccessTokenBasedRefresh(true).WithEmptyAccessToken().Build()),
method: http.MethodGet, method: http.MethodGet,
path: happyGetRequestPath, path: happyGetRequestPath,
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername), customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
@ -1091,8 +1084,34 @@ func TestAuthorizationEndpoint(t *testing.T) {
wantBodyString: "", wantBodyString: "",
}, },
{ {
name: "return an error when upstream IDP did not return an access or refresh token and allowAccessTokenBasedRefresh is true", name: "return an error when upstream IDP returns no refresh and no access token",
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithEmptyRefreshToken().WithAllowAccessTokenBasedRefresh(true).WithoutAccessToken().Build()), idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithoutRefreshToken().WithoutAccessToken().Build()),
method: http.MethodGet,
path: happyGetRequestPath,
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
wantStatus: http.StatusFound,
wantContentType: "application/json; charset=utf-8",
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithMissingAccessTokenErrorQuery),
wantBodyString: "",
},
{
name: "return an error when upstream IDP returns no refresh token and empty access token",
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithoutRefreshToken().WithEmptyAccessToken().Build()),
method: http.MethodGet,
path: happyGetRequestPath,
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
wantStatus: http.StatusFound,
wantContentType: "application/json; charset=utf-8",
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithMissingAccessTokenErrorQuery),
wantBodyString: "",
},
{
name: "return an error when upstream IDP returns empty refresh token and no access token",
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithEmptyRefreshToken().WithoutAccessToken().Build()),
method: http.MethodGet, method: http.MethodGet,
path: happyGetRequestPath, path: happyGetRequestPath,
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername), customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),

View File

@ -46,10 +46,6 @@ type UpstreamOIDCIdentityProviderI interface {
// flow with this upstream provider. When false, it should not be allowed. // flow with this upstream provider. When false, it should not be allowed.
AllowsPasswordGrant() bool AllowsPasswordGrant() bool
// AllowsAccessTokenBasedRefresh returns true if the supervisor should be allowed to refresh upstream
// users with an access token rather than a refresh token.
AllowsAccessTokenBasedRefresh() bool
// GetAdditionalAuthcodeParams returns additional params to be sent on authcode requests. // GetAdditionalAuthcodeParams returns additional params to be sent on authcode requests.
GetAdditionalAuthcodeParams() map[string]string GetAdditionalAuthcodeParams() map[string]string

View File

@ -74,9 +74,14 @@ type OIDCSessionData struct {
// non-empty, then this field should be empty, indicating that we should use the upstream refresh token during // non-empty, then this field should be empty, indicating that we should use the upstream refresh token during
// downstream refresh. // downstream refresh.
UpstreamAccessToken string `json:"upstreamAccessToken"` UpstreamAccessToken string `json:"upstreamAccessToken"`
// TODO describe these
// UpstreamSubject is the "sub" claim from the upstream identity provider from the user's initial login. We store this
// so that we can validate that it does not change upon refresh.
UpstreamSubject string `json:"upstreamSubject"` UpstreamSubject string `json:"upstreamSubject"`
UpstreamIssuer string `json:"upstreamIssuer"`
// UpstreamIssuer is the "iss" claim from the upstream identity provider from the user's initial login. We store this
// so that we can validate that it does not change upon refresh.
UpstreamIssuer string `json:"upstreamIssuer"`
} }
// LDAPSessionData is the additional data needed by Pinniped when the upstream IDP is an LDAP provider. // LDAPSessionData is the additional data needed by Pinniped when the upstream IDP is an LDAP provider.

View File

@ -146,17 +146,16 @@ func (u *TestUpstreamLDAPIdentityProvider) PerformRefreshArgs(call int) *Perform
} }
type TestUpstreamOIDCIdentityProvider struct { type TestUpstreamOIDCIdentityProvider struct {
Name string Name string
ClientID string ClientID string
ResourceUID types.UID ResourceUID types.UID
AuthorizationURL url.URL AuthorizationURL url.URL
RevocationURL *url.URL RevocationURL *url.URL
UsernameClaim string UsernameClaim string
GroupsClaim string GroupsClaim string
Scopes []string Scopes []string
AdditionalAuthcodeParams map[string]string AdditionalAuthcodeParams map[string]string
AllowPasswordGrant bool AllowPasswordGrant bool
AllowAccessTokenBasedRefresh bool
ExchangeAuthcodeAndValidateTokensFunc func( ExchangeAuthcodeAndValidateTokensFunc func(
ctx context.Context, ctx context.Context,
@ -231,10 +230,6 @@ func (u *TestUpstreamOIDCIdentityProvider) AllowsPasswordGrant() bool {
return u.AllowPasswordGrant return u.AllowPasswordGrant
} }
func (u *TestUpstreamOIDCIdentityProvider) AllowsAccessTokenBasedRefresh() bool {
return u.AllowAccessTokenBasedRefresh
}
func (u *TestUpstreamOIDCIdentityProvider) PasswordCredentialsGrantAndValidateTokens(ctx context.Context, username, password string) (*oidctypes.Token, error) { func (u *TestUpstreamOIDCIdentityProvider) PasswordCredentialsGrantAndValidateTokens(ctx context.Context, username, password string) (*oidctypes.Token, error) {
u.passwordCredentialsGrantAndValidateTokensCallCount++ u.passwordCredentialsGrantAndValidateTokensCallCount++
u.passwordCredentialsGrantAndValidateTokensArgs = append(u.passwordCredentialsGrantAndValidateTokensArgs, &PasswordCredentialsGrantAndValidateTokensArgs{ u.passwordCredentialsGrantAndValidateTokensArgs = append(u.passwordCredentialsGrantAndValidateTokensArgs, &PasswordCredentialsGrantAndValidateTokensArgs{
@ -605,26 +600,25 @@ func NewUpstreamIDPListerBuilder() *UpstreamIDPListerBuilder {
} }
type TestUpstreamOIDCIdentityProviderBuilder struct { type TestUpstreamOIDCIdentityProviderBuilder struct {
name string name string
resourceUID types.UID resourceUID types.UID
clientID string clientID string
scopes []string scopes []string
idToken map[string]interface{} idToken map[string]interface{}
refreshToken *oidctypes.RefreshToken refreshToken *oidctypes.RefreshToken
accessToken *oidctypes.AccessToken accessToken *oidctypes.AccessToken
usernameClaim string usernameClaim string
groupsClaim string groupsClaim string
refreshedTokens *oauth2.Token refreshedTokens *oauth2.Token
validatedTokens *oidctypes.Token validatedTokens *oidctypes.Token
authorizationURL url.URL authorizationURL url.URL
additionalAuthcodeParams map[string]string additionalAuthcodeParams map[string]string
allowPasswordGrant bool allowPasswordGrant bool
allowAccessTokenBasedRefresh bool authcodeExchangeErr error
authcodeExchangeErr error passwordGrantErr error
passwordGrantErr error performRefreshErr error
performRefreshErr error revokeRefreshTokenErr error
revokeRefreshTokenErr error validateTokenErr error
validateTokenErr error
} }
func (u *TestUpstreamOIDCIdentityProviderBuilder) WithName(value string) *TestUpstreamOIDCIdentityProviderBuilder { func (u *TestUpstreamOIDCIdentityProviderBuilder) WithName(value string) *TestUpstreamOIDCIdentityProviderBuilder {
@ -652,11 +646,6 @@ func (u *TestUpstreamOIDCIdentityProviderBuilder) WithAllowPasswordGrant(value b
return u return u
} }
func (u *TestUpstreamOIDCIdentityProviderBuilder) WithAllowAccessTokenBasedRefresh(value bool) *TestUpstreamOIDCIdentityProviderBuilder {
u.allowAccessTokenBasedRefresh = value
return u
}
func (u *TestUpstreamOIDCIdentityProviderBuilder) WithScopes(values []string) *TestUpstreamOIDCIdentityProviderBuilder { func (u *TestUpstreamOIDCIdentityProviderBuilder) WithScopes(values []string) *TestUpstreamOIDCIdentityProviderBuilder {
u.scopes = values u.scopes = values
return u return u
@ -766,16 +755,15 @@ func (u *TestUpstreamOIDCIdentityProviderBuilder) WithRevokeRefreshTokenError(er
func (u *TestUpstreamOIDCIdentityProviderBuilder) Build() *TestUpstreamOIDCIdentityProvider { func (u *TestUpstreamOIDCIdentityProviderBuilder) Build() *TestUpstreamOIDCIdentityProvider {
return &TestUpstreamOIDCIdentityProvider{ return &TestUpstreamOIDCIdentityProvider{
Name: u.name, Name: u.name,
ClientID: u.clientID, ClientID: u.clientID,
ResourceUID: u.resourceUID, ResourceUID: u.resourceUID,
UsernameClaim: u.usernameClaim, UsernameClaim: u.usernameClaim,
GroupsClaim: u.groupsClaim, GroupsClaim: u.groupsClaim,
Scopes: u.scopes, Scopes: u.scopes,
AllowPasswordGrant: u.allowPasswordGrant, AllowPasswordGrant: u.allowPasswordGrant,
AllowAccessTokenBasedRefresh: u.allowAccessTokenBasedRefresh, AuthorizationURL: u.authorizationURL,
AuthorizationURL: u.authorizationURL, AdditionalAuthcodeParams: u.additionalAuthcodeParams,
AdditionalAuthcodeParams: u.additionalAuthcodeParams,
ExchangeAuthcodeAndValidateTokensFunc: func(ctx context.Context, authcode string, pkceCodeVerifier pkce.Code, expectedIDTokenNonce nonce.Nonce) (*oidctypes.Token, error) { ExchangeAuthcodeAndValidateTokensFunc: func(ctx context.Context, authcode string, pkceCodeVerifier pkce.Code, expectedIDTokenNonce nonce.Nonce) (*oidctypes.Token, error) {
if u.authcodeExchangeErr != nil { if u.authcodeExchangeErr != nil {
return nil, u.authcodeExchangeErr return nil, u.authcodeExchangeErr

View File

@ -35,17 +35,16 @@ func New(config *oauth2.Config, provider *coreosoidc.Provider, client *http.Clie
// ProviderConfig holds the active configuration of an upstream OIDC provider. // ProviderConfig holds the active configuration of an upstream OIDC provider.
type ProviderConfig struct { type ProviderConfig struct {
Name string Name string
ResourceUID types.UID ResourceUID types.UID
UsernameClaim string UsernameClaim string
GroupsClaim string GroupsClaim string
Config *oauth2.Config Config *oauth2.Config
Client *http.Client Client *http.Client
AllowPasswordGrant bool AllowPasswordGrant bool
AllowAccessTokenBasedRefresh bool AdditionalAuthcodeParams map[string]string
AdditionalAuthcodeParams map[string]string RevocationURL *url.URL // will commonly be nil: many providers do not offer this
RevocationURL *url.URL // will commonly be nil: many providers do not offer this Provider interface {
Provider interface {
Verifier(*coreosoidc.Config) *coreosoidc.IDTokenVerifier Verifier(*coreosoidc.Config) *coreosoidc.IDTokenVerifier
Claims(v interface{}) error Claims(v interface{}) error
UserInfo(ctx context.Context, tokenSource oauth2.TokenSource) (*coreosoidc.UserInfo, error) UserInfo(ctx context.Context, tokenSource oauth2.TokenSource) (*coreosoidc.UserInfo, error)
@ -95,10 +94,6 @@ func (p *ProviderConfig) AllowsPasswordGrant() bool {
return p.AllowPasswordGrant return p.AllowPasswordGrant
} }
func (p *ProviderConfig) AllowsAccessTokenBasedRefresh() bool {
return p.AllowAccessTokenBasedRefresh
}
func (p *ProviderConfig) PasswordCredentialsGrantAndValidateTokens(ctx context.Context, username, password string) (*oidctypes.Token, error) { func (p *ProviderConfig) PasswordCredentialsGrantAndValidateTokens(ctx context.Context, username, password string) (*oidctypes.Token, error) {
// Disallow this grant when requested. // Disallow this grant when requested.
if !p.AllowPasswordGrant { if !p.AllowPasswordGrant {

View File

@ -1,4 +1,4 @@
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
package oidcclient package oidcclient
@ -406,7 +406,7 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
h.getProvider = func(config *oauth2.Config, provider *oidc.Provider, client *http.Client) provider.UpstreamOIDCIdentityProviderI { h.getProvider = func(config *oauth2.Config, provider *oidc.Provider, client *http.Client) provider.UpstreamOIDCIdentityProviderI {
mock := mockUpstream(t) mock := mockUpstream(t)
mock.EXPECT(). mock.EXPECT().
ValidateToken(gomock.Any(), HasAccessToken(testToken.AccessToken.Token), nonce.Nonce(""), true). ValidateTokenAndMergeWithUserInfo(gomock.Any(), HasAccessToken(testToken.AccessToken.Token), nonce.Nonce(""), true).
Return(&testToken, nil) Return(&testToken, nil)
mock.EXPECT(). mock.EXPECT().
PerformRefresh(gomock.Any(), testToken.RefreshToken.Token). PerformRefresh(gomock.Any(), testToken.RefreshToken.Token).
@ -453,7 +453,7 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
h.getProvider = func(config *oauth2.Config, provider *oidc.Provider, client *http.Client) provider.UpstreamOIDCIdentityProviderI { h.getProvider = func(config *oauth2.Config, provider *oidc.Provider, client *http.Client) provider.UpstreamOIDCIdentityProviderI {
mock := mockUpstream(t) mock := mockUpstream(t)
mock.EXPECT(). mock.EXPECT().
ValidateToken(gomock.Any(), HasAccessToken(testToken.AccessToken.Token), nonce.Nonce(""), true). ValidateTokenAndMergeWithUserInfo(gomock.Any(), HasAccessToken(testToken.AccessToken.Token), nonce.Nonce(""), true).
Return(nil, fmt.Errorf("some validation error")) Return(nil, fmt.Errorf("some validation error"))
mock.EXPECT(). mock.EXPECT().
PerformRefresh(gomock.Any(), "test-refresh-token-returning-invalid-id-token"). PerformRefresh(gomock.Any(), "test-refresh-token-returning-invalid-id-token").
@ -1648,7 +1648,7 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
h.getProvider = func(config *oauth2.Config, provider *oidc.Provider, client *http.Client) provider.UpstreamOIDCIdentityProviderI { h.getProvider = func(config *oauth2.Config, provider *oidc.Provider, client *http.Client) provider.UpstreamOIDCIdentityProviderI {
mock := mockUpstream(t) mock := mockUpstream(t)
mock.EXPECT(). mock.EXPECT().
ValidateToken(gomock.Any(), HasAccessToken(testToken.AccessToken.Token), nonce.Nonce(""), true). ValidateTokenAndMergeWithUserInfo(gomock.Any(), HasAccessToken(testToken.AccessToken.Token), nonce.Nonce(""), true).
Return(&testToken, nil) Return(&testToken, nil)
mock.EXPECT(). mock.EXPECT().
PerformRefresh(gomock.Any(), testToken.RefreshToken.Token). PerformRefresh(gomock.Any(), testToken.RefreshToken.Token).

View File

@ -149,8 +149,7 @@ func TestSupervisorLogin(t *testing.T) {
Groups: env.SupervisorUpstreamOIDC.GroupsClaim, Groups: env.SupervisorUpstreamOIDC.GroupsClaim,
}, },
AuthorizationConfig: idpv1alpha1.OIDCAuthorizationConfig{ AuthorizationConfig: idpv1alpha1.OIDCAuthorizationConfig{
AdditionalScopes: []string{"email"}, // does not ask for offline_access. AdditionalScopes: []string{"email"}, // does not ask for offline_access.
AllowAccessTokenBasedRefresh: true,
}, },
}, idpv1alpha1.PhaseReady) }, idpv1alpha1.PhaseReady)
return oidcIDP.Name return oidcIDP.Name