Skip to content

Commit

Permalink
Merge pull request #14784 from liggitt/per-client-expiration
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue (batch tested with PRs 14784, 16418, 16406, 16431, 14796)

Per-client access token expiration

This allows overriding max access token age per OAuthClient.

https://trello.com/c/hNhBstvg

OAuthClient object gains a new field: accessTokenMaxAgeSeconds

* When absent, the master-config value is used
* When set to 0, tokens issued for that client do not expire
* When set to a value > 0, tokens issued for that client are given the specified expiration time
  • Loading branch information
openshift-merge-robot committed Sep 19, 2017
2 parents 7bb08c0 + a72b77b commit 660aa12
Show file tree
Hide file tree
Showing 21 changed files with 363 additions and 96 deletions.
3 changes: 2 additions & 1 deletion api/docs/apis-oauth.openshift.io/v1.OAuthClient.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ Expand or mouse-over a field for more information about it.

++++
<pre>
<details><summary><span title="(array) AdditionalSecrets holds other secrets that may be used to identify the client. This is useful for rotation and for service account token validation">additionalSecrets</span>:
<div style="margin-left:13px;"><span title="(integer) AccessTokenMaxAgeSeconds overrides the default access token max age for tokens granted to this client. 0 means no expiration.">accessTokenMaxAgeSeconds</span>:
</div><details><summary><span title="(array) AdditionalSecrets holds other secrets that may be used to identify the client. This is useful for rotation and for service account token validation">additionalSecrets</span>:
</summary><div style="margin-left:13px;">- <span title="(string)">[string]</span>:
</div></details><div style="margin-left:13px;"><span title="(string) APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources">apiVersion</span>:
</div><div style="margin-left:13px;"><span title="(string) GrantMethod determines how to handle grants for this client. If no method is provided, the cluster default grant handling method will be used. Valid grant handling methods are:
Expand Down
3 changes: 2 additions & 1 deletion api/docs/oapi/v1.OAuthClient.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ Expand or mouse-over a field for more information about it.

++++
<pre>
<details><summary><span title="(array) AdditionalSecrets holds other secrets that may be used to identify the client. This is useful for rotation and for service account token validation">additionalSecrets</span>:
<div style="margin-left:13px;"><span title="(integer) AccessTokenMaxAgeSeconds overrides the default access token max age for tokens granted to this client. 0 means no expiration.">accessTokenMaxAgeSeconds</span>:
</div><details><summary><span title="(array) AdditionalSecrets holds other secrets that may be used to identify the client. This is useful for rotation and for service account token validation">additionalSecrets</span>:
</summary><div style="margin-left:13px;">- <span title="(string)">[string]</span>:
</div></details><div style="margin-left:13px;"><span title="(string) APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources">apiVersion</span>:
</div><div style="margin-left:13px;"><span title="(string) GrantMethod determines how to handle grants for this client. If no method is provided, the cluster default grant handling method will be used. Valid grant handling methods are:
Expand Down

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

5 changes: 5 additions & 0 deletions api/swagger-spec/oapi-v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -27218,6 +27218,11 @@
"$ref": "v1.ScopeRestriction"
},
"description": "ScopeRestrictions describes which scopes this client can request. Each requested scope is checked against each restriction. If any restriction matches, then the scope is allowed. If no restriction matches, then the scope is denied."
},
"accessTokenMaxAgeSeconds": {
"type": "integer",
"format": "int32",
"description": "AccessTokenMaxAgeSeconds overrides the default access token max age for tokens granted to this client. 0 means no expiration."
}
}
},
Expand Down
5 changes: 5 additions & 0 deletions api/swagger-spec/openshift-openapi-spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -91358,6 +91358,11 @@
"com.github.openshift.origin.pkg.oauth.apis.oauth.v1.OAuthClient": {
"description": "OAuthClient describes an OAuth client",
"properties": {
"accessTokenMaxAgeSeconds": {
"description": "AccessTokenMaxAgeSeconds overrides the default access token max age for tokens granted to this client. 0 means no expiration.",
"type": "integer",
"format": "int32"
},
"additionalSecrets": {
"description": "AdditionalSecrets holds other secrets that may be used to identify the client. This is useful for rotation and for service account token validation",
"type": "array",
Expand Down
14 changes: 14 additions & 0 deletions pkg/auth/oauth/handlers/authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ func NewAuthorizeAuthenticator(request authenticator.Request, handler Authentica
return &AuthorizeAuthenticator{request, handler, errorHandler}
}

type TokenMaxAgeSeconds interface {
// GetTokenMaxAgeSeconds returns the max age of the token in seconds.
// 0 means no expiration.
// nil means to use the default expiration.
GetTokenMaxAgeSeconds() *int32
}

// HandleAuthorize implements osinserver.AuthorizeHandler to ensure the AuthorizeRequest is authenticated.
// If the request is authenticated, UserData and Authorized are set and false is returned.
// If the request is not authenticated, the auth handler is called and the request is not authorized
Expand All @@ -38,6 +45,13 @@ func (h *AuthorizeAuthenticator) HandleAuthorize(ar *osin.AuthorizeRequest, resp
glog.V(4).Infof("OAuth authentication succeeded: %#v", info)
ar.UserData = info
ar.Authorized = true

if e, ok := ar.Client.(TokenMaxAgeSeconds); ok {
if maxAge := e.GetTokenMaxAgeSeconds(); maxAge != nil {
ar.Expiration = *maxAge
}
}

return false, nil
}

Expand Down
6 changes: 4 additions & 2 deletions pkg/auth/oauth/registry/tokenauthenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ func (a *TokenAuthenticator) AuthenticateToken(value string) (kuser.Info, bool,
if err != nil {
return nil, false, err
}
if token.CreationTimestamp.Time.Add(time.Duration(token.ExpiresIn) * time.Second).Before(time.Now()) {
return nil, false, ErrExpired
if token.ExpiresIn > 0 {
if token.CreationTimestamp.Time.Add(time.Duration(token.ExpiresIn) * time.Second).Before(time.Now()) {
return nil, false, ErrExpired
}
}
if token.DeletionTimestamp != nil {
return nil, false, ErrExpired
Expand Down
12 changes: 8 additions & 4 deletions pkg/cmd/util/tokencmd/request_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,16 @@ type ChallengeHandler interface {
type RequestTokenOptions struct {
ClientConfig *restclient.Config
Handler ChallengeHandler
ClientID string
}

// RequestToken uses the cmd arguments to locate an openshift oauth server and attempts to authenticate
// it returns the access token if it gets one. An error if it does not
func RequestToken(clientCfg *restclient.Config, reader io.Reader, defaultUsername string, defaultPassword string) (string, error) {
return NewRequestTokenOptions(clientCfg, reader, defaultUsername, defaultPassword).RequestToken()
}

func NewRequestTokenOptions(clientCfg *restclient.Config, reader io.Reader, defaultUsername string, defaultPassword string) *RequestTokenOptions {
handlers := []ChallengeHandler{}
if GSSAPIEnabled() {
handlers = append(handlers, NewNegotiateChallengeHandler(NewGSSAPINegotiator(defaultUsername)))
Expand All @@ -62,12 +67,11 @@ func RequestToken(clientCfg *restclient.Config, reader io.Reader, defaultUsernam
handler = NewMultiHandler(handlers...)
}

opts := &RequestTokenOptions{
return &RequestTokenOptions{
ClientConfig: clientCfg,
Handler: handler,
ClientID: "openshift-challenging-client",
}

return opts.RequestToken()
}

// RequestToken locates an openshift oauth server and attempts to authenticate.
Expand All @@ -89,7 +93,7 @@ func (o *RequestTokenOptions) RequestToken() (string, error) {
}

// requestURL holds the current URL to make requests to. This can change if the server responds with a redirect
requestURL := o.ClientConfig.Host + "/oauth/authorize?response_type=token&client_id=openshift-challenging-client"
requestURL := o.ClientConfig.Host + "/oauth/authorize?" + url.Values{"response_type": []string{"token"}, "client_id": []string{o.ClientID}}.Encode()
// requestHeaders holds additional headers to add to the request. This can be changed by o.Handlers
requestHeaders := http.Header{}
// requestedURLSet/requestedURLList hold the URLs we have requested, to prevent redirect loops. Gets reset when a challenge is handled.
Expand Down
4 changes: 4 additions & 0 deletions pkg/oauth/apis/oauth/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ type OAuthClient struct {
// is checked against each restriction. If any restriction matches, then the scope is allowed.
// If no restriction matches, then the scope is denied.
ScopeRestrictions []ScopeRestriction

// AccessTokenMaxAgeSeconds overrides the default access token max age for tokens granted to this client.
// 0 means no expiration.
AccessTokenMaxAgeSeconds *int32
}

type GrantHandlerType string
Expand Down
Loading

0 comments on commit 660aa12

Please sign in to comment.