Skip to content

Commit

Permalink
Implement handling OAuth2 client token lifespans.
Browse files Browse the repository at this point in the history
  • Loading branch information
David-Wobrock committed Jun 23, 2024
1 parent 0c846f2 commit 0cb8255
Show file tree
Hide file tree
Showing 7 changed files with 483 additions and 331 deletions.
67 changes: 67 additions & 0 deletions api/v1alpha1/oauth2client_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,69 @@ type HydraAdmin struct {
ForwardedProto string `json:"forwardedProto,omitempty"`
}

// TokenLifespans defines the desired token durations by grant type for OAuth2Client
type TokenLifespans struct {
// +kubebuilder:validation:Pattern=[0-9]+(ns|us|ms|s|m|h)
//
// AuthorizationCodeGrantAccessTokenLifespan is the access token lifespan
// issued on an authorization_code grant.
AuthorizationCodeGrantAccessTokenLifespan string `json:"authorization_code_grant_access_token_lifespan,omitempty"`

// +kubebuilder:validation:Pattern=[0-9]+(ns|us|ms|s|m|h)
//
// AuthorizationCodeGrantIdTokenLifespan is the id token lifespan
// issued on an authorization_code grant.
AuthorizationCodeGrantIdTokenLifespan string `json:"authorization_code_grant_id_token_lifespan,omitempty"`

// +kubebuilder:validation:Pattern=[0-9]+(ns|us|ms|s|m|h)
//
// AuthorizationCodeGrantRefreshTokenLifespan is the refresh token lifespan
// issued on an authorization_code grant.
AuthorizationCodeGrantRefreshTokenLifespan string `json:"authorization_code_grant_refresh_token_lifespan,omitempty"`

// +kubebuilder:validation:Pattern=[0-9]+(ns|us|ms|s|m|h)
//
// AuthorizationCodeGrantRefreshTokenLifespan is the access token lifespan
// issued on a client_credentials grant.
ClientCredentialsGrantAccessTokenLifespan string `json:"client_credentials_grant_access_token_lifespan,omitempty"`

// +kubebuilder:validation:Pattern=[0-9]+(ns|us|ms|s|m|h)
//
// ImplicitGrantAccessTokenLifespan is the access token lifespan
// issued on an implicit grant.
ImplicitGrantAccessTokenLifespan string `json:"implicit_grant_access_token_lifespan,omitempty"`

// +kubebuilder:validation:Pattern=[0-9]+(ns|us|ms|s|m|h)
//
// ImplicitGrantIdTokenLifespan is the id token lifespan
// issued on an implicit grant.
ImplicitGrantIdTokenLifespan string `json:"implicit_grant_id_token_lifespan,omitempty"`

// +kubebuilder:validation:Pattern=[0-9]+(ns|us|ms|s|m|h)
//
// JwtBearerGrantAccessTokenLifespan is the access token lifespan
// issued on a jwt_bearer grant.
JwtBearerGrantAccessTokenLifespan string `json:"jwt_bearer_grant_access_token_lifespan,omitempty"`

// +kubebuilder:validation:Pattern=[0-9]+(ns|us|ms|s|m|h)
//
// RefreshTokenGrantAccessTokenLifespan is the access token lifespan
// issued on a refresh_token grant.
RefreshTokenGrantAccessTokenLifespan string `json:"refresh_token_grant_access_token_lifespan,omitempty"`

// +kubebuilder:validation:Pattern=[0-9]+(ns|us|ms|s|m|h)
//
// RefreshTokenGrantIdTokenLifespan is the id token lifespan
// issued on a refresh_token grant.
RefreshTokenGrantIdTokenLifespan string `json:"refresh_token_grant_id_token_lifespan,omitempty"`

// +kubebuilder:validation:Pattern=[0-9]+(ns|us|ms|s|m|h)
//
// RefreshTokenGrantRefreshTokenLifespan is the refresh token lifespan
// issued on a refresh_token grant.
RefreshTokenGrantRefreshTokenLifespan string `json:"refresh_token_grant_refresh_token_lifespan,omitempty"`
}

// OAuth2ClientSpec defines the desired state of OAuth2Client
type OAuth2ClientSpec struct {

Expand Down Expand Up @@ -110,6 +173,10 @@ type OAuth2ClientSpec struct {
// Indication which authentication method shoud be used for the token endpoint
TokenEndpointAuthMethod TokenEndpointAuthMethod `json:"tokenEndpointAuthMethod,omitempty"`

// TokenLifespans is the configuration to use for managing different token lifespans
// depending on the used grant type.
TokenLifespans TokenLifespans `json:"tokenLifespans,omitempty"`

// +kubebuilder:validation:Type=object
// +nullable
// +optional
Expand Down
41 changes: 26 additions & 15 deletions api/v1alpha1/oauth2client_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,27 @@ func TestCreateAPI(t *testing.T) {
t.Run("by failing if the requested object doesn't meet CRD requirements", func(t *testing.T) {

for desc, modifyClient := range map[string]func(){
"invalid grant type": func() { created.Spec.GrantTypes = []GrantType{"invalid"} },
"invalid response type": func() { created.Spec.ResponseTypes = []ResponseType{"invalid", "code"} },
"invalid composite response type": func() { created.Spec.ResponseTypes = []ResponseType{"invalid code", "code id_token"} },
"invalid scope": func() { created.Spec.Scope = "" },
"missing secret name": func() { created.Spec.SecretName = "" },
"invalid redirect URI": func() { created.Spec.RedirectURIs = []RedirectURI{"invalid"} },
"invalid logout redirect URI": func() { created.Spec.PostLogoutRedirectURIs = []RedirectURI{"invalid"} },
"invalid hydra url": func() { created.Spec.HydraAdmin.URL = "invalid" },
"invalid hydra port high": func() { created.Spec.HydraAdmin.Port = 65536 },
"invalid hydra endpoint": func() { created.Spec.HydraAdmin.Endpoint = "invalid" },
"invalid hydra forwarded proto": func() { created.Spec.HydraAdmin.Endpoint = "invalid" },
"invalid grant type": func() { created.Spec.GrantTypes = []GrantType{"invalid"} },
"invalid response type": func() { created.Spec.ResponseTypes = []ResponseType{"invalid", "code"} },
"invalid composite response type": func() { created.Spec.ResponseTypes = []ResponseType{"invalid code", "code id_token"} },
"invalid scope": func() { created.Spec.Scope = "" },
"missing secret name": func() { created.Spec.SecretName = "" },
"invalid redirect URI": func() { created.Spec.RedirectURIs = []RedirectURI{"invalid"} },
"invalid logout redirect URI": func() { created.Spec.PostLogoutRedirectURIs = []RedirectURI{"invalid"} },
"invalid hydra url": func() { created.Spec.HydraAdmin.URL = "invalid" },
"invalid hydra port high": func() { created.Spec.HydraAdmin.Port = 65536 },
"invalid hydra endpoint": func() { created.Spec.HydraAdmin.Endpoint = "invalid" },
"invalid hydra forwarded proto": func() { created.Spec.HydraAdmin.ForwardedProto = "invalid" },
"invalid lifespan authorization code access token": func() { created.Spec.TokenLifespans.AuthorizationCodeGrantAccessTokenLifespan = "invalid" },
"invalid lifespan authorization code id token": func() { created.Spec.TokenLifespans.AuthorizationCodeGrantIdTokenLifespan = "invalid" },
"invalid lifespan authorization code refresh token": func() { created.Spec.TokenLifespans.AuthorizationCodeGrantRefreshTokenLifespan = "invalid" },
"invalid lifespan client credentials access token": func() { created.Spec.TokenLifespans.ClientCredentialsGrantAccessTokenLifespan = "invalid" },
"invalid lifespan implicit access token": func() { created.Spec.TokenLifespans.ImplicitGrantAccessTokenLifespan = "invalid" },
"invalid lifespan implicit id token": func() { created.Spec.TokenLifespans.ImplicitGrantIdTokenLifespan = "invalid" },
"invalid lifespan jwt bearer access token": func() { created.Spec.TokenLifespans.JwtBearerGrantAccessTokenLifespan = "invalid" },
"invalid lifespan refresh token access token": func() { created.Spec.TokenLifespans.RefreshTokenGrantAccessTokenLifespan = "invalid" },
"invalid lifespan refresh token id token": func() { created.Spec.TokenLifespans.RefreshTokenGrantIdTokenLifespan = "invalid" },
"invalid lifespan refresh token refresh token": func() { created.Spec.TokenLifespans.RefreshTokenGrantRefreshTokenLifespan = "invalid" },
} {
t.Run(fmt.Sprintf("case=%s", desc), func(t *testing.T) {
resetTestClient()
Expand Down Expand Up @@ -158,10 +168,11 @@ func resetTestClient() {
Namespace: "default",
},
Spec: OAuth2ClientSpec{
GrantTypes: []GrantType{"implicit", "client_credentials", "authorization_code", "refresh_token"},
ResponseTypes: []ResponseType{"id_token", "code", "token"},
Scope: "read,write",
SecretName: "secret-name",
GrantTypes: []GrantType{"implicit", "client_credentials", "authorization_code", "refresh_token"},
ResponseTypes: []ResponseType{"id_token", "code", "token"},
Scope: "read,write",
SecretName: "secret-name",
TokenLifespans: TokenLifespans{},
},
}
}
17 changes: 16 additions & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 0cb8255

Please sign in to comment.