2016-07-26 01:30:28 +05:30
|
|
|
package kubernetes
|
|
|
|
|
|
|
|
import (
|
2016-10-06 04:34:48 +05:30
|
|
|
"strings"
|
2016-07-26 01:30:28 +05:30
|
|
|
"time"
|
|
|
|
|
|
|
|
jose "gopkg.in/square/go-jose.v2"
|
|
|
|
|
2018-09-03 12:14:44 +05:30
|
|
|
"github.com/dexidp/dex/storage"
|
|
|
|
"github.com/dexidp/dex/storage/kubernetes/k8sapi"
|
2016-07-26 01:30:28 +05:30
|
|
|
)
|
|
|
|
|
2017-09-13 23:27:54 +05:30
|
|
|
var crdMeta = k8sapi.TypeMeta{
|
|
|
|
APIVersion: "apiextensions.k8s.io/v1beta1",
|
|
|
|
Kind: "CustomResourceDefinition",
|
|
|
|
}
|
|
|
|
|
|
|
|
const apiGroup = "dex.coreos.com"
|
|
|
|
|
|
|
|
// The set of custom resource definitions required by the storage. These are managed by
|
|
|
|
// the storage so it can migrate itself by creating new resources.
|
|
|
|
var customResourceDefinitions = []k8sapi.CustomResourceDefinition{
|
|
|
|
{
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: "authcodes.dex.coreos.com",
|
|
|
|
},
|
|
|
|
TypeMeta: crdMeta,
|
|
|
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
|
|
|
Group: apiGroup,
|
|
|
|
Version: "v1",
|
|
|
|
Names: k8sapi.CustomResourceDefinitionNames{
|
|
|
|
Plural: "authcodes",
|
|
|
|
Singular: "authcode",
|
|
|
|
Kind: "AuthCode",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: "authrequests.dex.coreos.com",
|
|
|
|
},
|
|
|
|
TypeMeta: crdMeta,
|
|
|
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
|
|
|
Group: apiGroup,
|
|
|
|
Version: "v1",
|
|
|
|
Names: k8sapi.CustomResourceDefinitionNames{
|
|
|
|
Plural: "authrequests",
|
2017-09-14 02:08:10 +05:30
|
|
|
Singular: "authrequest",
|
|
|
|
Kind: "AuthRequest",
|
2017-09-13 23:27:54 +05:30
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: "oauth2clients.dex.coreos.com",
|
|
|
|
},
|
|
|
|
TypeMeta: crdMeta,
|
|
|
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
|
|
|
Group: apiGroup,
|
|
|
|
Version: "v1",
|
|
|
|
Names: k8sapi.CustomResourceDefinitionNames{
|
|
|
|
Plural: "oauth2clients",
|
|
|
|
Singular: "oauth2client",
|
2017-09-14 02:08:10 +05:30
|
|
|
Kind: "OAuth2Client",
|
2017-09-13 23:27:54 +05:30
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: "signingkeies.dex.coreos.com",
|
|
|
|
},
|
|
|
|
TypeMeta: crdMeta,
|
|
|
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
|
|
|
Group: apiGroup,
|
|
|
|
Version: "v1",
|
|
|
|
Names: k8sapi.CustomResourceDefinitionNames{
|
2017-09-14 02:08:10 +05:30
|
|
|
// `signingkeies` is an artifact from the old TPR pluralization.
|
|
|
|
// Users don't directly interact with this value, hence leaving it
|
|
|
|
// as is.
|
2017-09-13 23:27:54 +05:30
|
|
|
Plural: "signingkeies",
|
|
|
|
Singular: "signingkey",
|
|
|
|
Kind: "SigningKey",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: "refreshtokens.dex.coreos.com",
|
|
|
|
},
|
|
|
|
TypeMeta: crdMeta,
|
|
|
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
|
|
|
Group: apiGroup,
|
|
|
|
Version: "v1",
|
|
|
|
Names: k8sapi.CustomResourceDefinitionNames{
|
|
|
|
Plural: "refreshtokens",
|
|
|
|
Singular: "refreshtoken",
|
|
|
|
Kind: "RefreshToken",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: "passwords.dex.coreos.com",
|
|
|
|
},
|
|
|
|
TypeMeta: crdMeta,
|
|
|
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
|
|
|
Group: apiGroup,
|
|
|
|
Version: "v1",
|
|
|
|
Names: k8sapi.CustomResourceDefinitionNames{
|
|
|
|
Plural: "passwords",
|
|
|
|
Singular: "password",
|
|
|
|
Kind: "Password",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: "offlinesessionses.dex.coreos.com",
|
|
|
|
},
|
|
|
|
TypeMeta: crdMeta,
|
|
|
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
|
|
|
Group: apiGroup,
|
|
|
|
Version: "v1",
|
|
|
|
Names: k8sapi.CustomResourceDefinitionNames{
|
|
|
|
Plural: "offlinesessionses",
|
|
|
|
Singular: "offlinesessions",
|
2017-09-20 03:28:42 +05:30
|
|
|
Kind: "OfflineSessions",
|
2017-09-13 23:27:54 +05:30
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: "connectors.dex.coreos.com",
|
|
|
|
},
|
|
|
|
TypeMeta: crdMeta,
|
|
|
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
|
|
|
Group: apiGroup,
|
|
|
|
Version: "v1",
|
|
|
|
Names: k8sapi.CustomResourceDefinitionNames{
|
|
|
|
Plural: "connectors",
|
|
|
|
Singular: "connector",
|
|
|
|
Kind: "Connector",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2020-01-16 21:25:07 +05:30
|
|
|
{
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: "devicerequests.dex.coreos.com",
|
|
|
|
},
|
|
|
|
TypeMeta: crdMeta,
|
|
|
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
|
|
|
Group: apiGroup,
|
|
|
|
Version: "v1",
|
|
|
|
Names: k8sapi.CustomResourceDefinitionNames{
|
|
|
|
Plural: "devicerequests",
|
|
|
|
Singular: "devicerequest",
|
|
|
|
Kind: "DeviceRequest",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: "devicetokens.dex.coreos.com",
|
|
|
|
},
|
|
|
|
TypeMeta: crdMeta,
|
|
|
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
|
|
|
Group: apiGroup,
|
|
|
|
Version: "v1",
|
|
|
|
Names: k8sapi.CustomResourceDefinitionNames{
|
|
|
|
Plural: "devicetokens",
|
|
|
|
Singular: "devicetoken",
|
|
|
|
Kind: "DeviceToken",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2017-09-13 23:27:54 +05:30
|
|
|
}
|
|
|
|
|
2016-07-26 01:30:28 +05:30
|
|
|
// There will only ever be a single keys resource. Maintain this by setting a
|
|
|
|
// common name.
|
|
|
|
const keysName = "openid-connect-keys"
|
|
|
|
|
|
|
|
// Client is a mirrored struct from storage with JSON struct tags and
|
|
|
|
// Kubernetes type metadata.
|
|
|
|
type Client struct {
|
2016-10-28 04:25:23 +05:30
|
|
|
// Name is a hash of the ID.
|
2016-07-26 01:30:28 +05:30
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ObjectMeta `json:"metadata,omitempty"`
|
|
|
|
|
2016-10-28 04:25:23 +05:30
|
|
|
// ID is immutable, since it's a primary key and should not be changed.
|
|
|
|
ID string `json:"id,omitempty"`
|
|
|
|
|
2016-07-26 01:30:28 +05:30
|
|
|
Secret string `json:"secret,omitempty"`
|
|
|
|
RedirectURIs []string `json:"redirectURIs,omitempty"`
|
|
|
|
TrustedPeers []string `json:"trustedPeers,omitempty"`
|
|
|
|
|
|
|
|
Public bool `json:"public"`
|
|
|
|
|
|
|
|
Name string `json:"name,omitempty"`
|
|
|
|
LogoURL string `json:"logoURL,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// ClientList is a list of Clients.
|
|
|
|
type ClientList struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ListMeta `json:"metadata,omitempty"`
|
|
|
|
Clients []Client `json:"items"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cli *client) fromStorageClient(c storage.Client) Client {
|
|
|
|
return Client{
|
|
|
|
TypeMeta: k8sapi.TypeMeta{
|
|
|
|
Kind: kindClient,
|
2016-10-14 05:20:20 +05:30
|
|
|
APIVersion: cli.apiVersion,
|
2016-07-26 01:30:28 +05:30
|
|
|
},
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
2016-10-28 04:25:23 +05:30
|
|
|
Name: cli.idToName(c.ID),
|
2016-07-26 01:30:28 +05:30
|
|
|
Namespace: cli.namespace,
|
|
|
|
},
|
2016-10-28 04:25:23 +05:30
|
|
|
ID: c.ID,
|
2016-07-26 01:30:28 +05:30
|
|
|
Secret: c.Secret,
|
|
|
|
RedirectURIs: c.RedirectURIs,
|
|
|
|
TrustedPeers: c.TrustedPeers,
|
|
|
|
Public: c.Public,
|
|
|
|
Name: c.Name,
|
|
|
|
LogoURL: c.LogoURL,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func toStorageClient(c Client) storage.Client {
|
|
|
|
return storage.Client{
|
2016-10-28 04:25:23 +05:30
|
|
|
ID: c.ID,
|
2016-07-26 01:30:28 +05:30
|
|
|
Secret: c.Secret,
|
|
|
|
RedirectURIs: c.RedirectURIs,
|
|
|
|
TrustedPeers: c.TrustedPeers,
|
|
|
|
Public: c.Public,
|
|
|
|
Name: c.Name,
|
|
|
|
LogoURL: c.LogoURL,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-03 10:27:36 +05:30
|
|
|
// Claims is a mirrored struct from storage with JSON struct tags.
|
|
|
|
type Claims struct {
|
2019-10-10 20:13:41 +05:30
|
|
|
UserID string `json:"userID"`
|
|
|
|
Username string `json:"username"`
|
|
|
|
PreferredUsername string `json:"preferredUsername"`
|
|
|
|
Email string `json:"email"`
|
|
|
|
EmailVerified bool `json:"emailVerified"`
|
|
|
|
Groups []string `json:"groups,omitempty"`
|
2016-07-26 01:30:28 +05:30
|
|
|
}
|
|
|
|
|
2016-08-03 10:27:36 +05:30
|
|
|
func fromStorageClaims(i storage.Claims) Claims {
|
|
|
|
return Claims{
|
2019-10-10 20:13:41 +05:30
|
|
|
UserID: i.UserID,
|
|
|
|
Username: i.Username,
|
|
|
|
PreferredUsername: i.PreferredUsername,
|
|
|
|
Email: i.Email,
|
|
|
|
EmailVerified: i.EmailVerified,
|
|
|
|
Groups: i.Groups,
|
2016-07-26 01:30:28 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-03 10:27:36 +05:30
|
|
|
func toStorageClaims(i Claims) storage.Claims {
|
|
|
|
return storage.Claims{
|
2019-10-10 20:13:41 +05:30
|
|
|
UserID: i.UserID,
|
|
|
|
Username: i.Username,
|
|
|
|
PreferredUsername: i.PreferredUsername,
|
|
|
|
Email: i.Email,
|
|
|
|
EmailVerified: i.EmailVerified,
|
|
|
|
Groups: i.Groups,
|
2016-07-26 01:30:28 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// AuthRequest is a mirrored struct from storage with JSON struct tags and
|
|
|
|
// Kubernetes type metadata.
|
|
|
|
type AuthRequest struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ObjectMeta `json:"metadata,omitempty"`
|
|
|
|
|
|
|
|
ClientID string `json:"clientID"`
|
|
|
|
ResponseTypes []string `json:"responseTypes,omitempty"`
|
|
|
|
Scopes []string `json:"scopes,omitempty"`
|
|
|
|
RedirectURI string `json:"redirectURI"`
|
|
|
|
|
|
|
|
Nonce string `json:"nonce,omitempty"`
|
|
|
|
State string `json:"state,omitempty"`
|
|
|
|
|
|
|
|
// The client has indicated that the end user must be shown an approval prompt
|
|
|
|
// on all requests. The server cannot cache their initial action for subsequent
|
|
|
|
// attempts.
|
|
|
|
ForceApprovalPrompt bool `json:"forceApprovalPrompt,omitempty"`
|
|
|
|
|
2016-09-15 05:08:12 +05:30
|
|
|
LoggedIn bool `json:"loggedIn"`
|
|
|
|
|
2016-07-26 01:30:28 +05:30
|
|
|
// The identity of the end user. Generally nil until the user authenticates
|
|
|
|
// with a backend.
|
2016-09-15 05:08:12 +05:30
|
|
|
Claims Claims `json:"claims,omitempty"`
|
2016-07-26 01:30:28 +05:30
|
|
|
// The connector used to login the user. Set when the user authenticates.
|
2019-04-18 19:48:50 +05:30
|
|
|
ConnectorID string `json:"connectorID,omitempty"`
|
|
|
|
ConnectorData []byte `json:"connectorData,omitempty"`
|
2016-07-26 01:30:28 +05:30
|
|
|
|
|
|
|
Expiry time.Time `json:"expiry"`
|
PKCE implementation (#1784)
* Basic implementation of PKCE
Signed-off-by: Tadeusz Magura-Witkowski <tadeuszmw@gmail.com>
* @mfmarche on 24 Feb: when code_verifier is set, don't check client_secret
In PKCE flow, no client_secret is used, so the check for a valid client_secret
would always fail.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* @deric on 16 Jun: return invalid_grant when wrong code_verifier
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Enforce PKCE flow on /token when PKCE flow was started on /auth
Also dissallow PKCE on /token, when PKCE flow was not started on /auth
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* fixed error messages when mixed PKCE/no PKCE flow.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* server_test.go: Added PKCE error cases on /token endpoint
* Added test for invalid_grant, when wrong code_verifier is sent
* Added test for mixed PKCE / no PKCE auth flows.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* cleanup: extracted method checkErrorResponse and type TestDefinition
* fixed connector being overwritten
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* /token endpoint: skip client_secret verification only for grand type authorization_code with PKCE extension
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Allow "Authorization" header in CORS handlers
* Adds "Authorization" to the default CORS headers{"Accept", "Accept-Language", "Content-Language", "Origin"}
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Add "code_challenge_methods_supported" to discovery endpoint
discovery endpoint /dex/.well-known/openid-configuration
now has the following entry:
"code_challenge_methods_supported": [
"S256",
"plain"
]
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Updated tests (mixed-up comments), added a PKCE test
* @asoorm added test that checks if downgrade to "plain" on /token endpoint
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* remove redefinition of providedCodeVerifier, fixed spelling (#6)
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
Signed-off-by: Bernd Eckstein <HEllRZA@users.noreply.github.com>
* Rename struct CodeChallenge to PKCE
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* PKCE: Check clientSecret when available
In authorization_code flow with PKCE, allow empty client_secret on /auth and /token endpoints. But check the client_secret when it is given.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Enable PKCE with public: true
dex configuration public on staticClients now enables the following behavior in PKCE:
- Public: false, PKCE will always check client_secret. This means PKCE in it's natural form is disabled.
- Public: true, PKCE is enabled. It will only check client_secret if the client has sent one. But it allows the code flow if the client didn't sent one.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Redirect error on unsupported code_challenge_method
- Check for unsupported code_challenge_method after redirect uri is validated, and use newErr() to return the error.
- Add PKCE tests to oauth2_test.go
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Reverted go.mod and go.sum to the state of master
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Don't omit client secret check for PKCE
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Allow public clients (e.g. with PKCE) to have redirect URIs configured
Signed-off-by: Martin Heide <martin.heide@faro.com>
* Remove "Authorization" as Accepted Headers on CORS, small fixes
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Revert "Allow public clients (e.g. with PKCE) to have redirect URIs configured"
This reverts commit b6e297b78537dc44cd3e1374f0b4d34bf89404ac.
Signed-off-by: Martin Heide <martin.heide@faro.com>
* PKCE on client_secret client error message
* When connecting to the token endpoint with PKCE without client_secret, but the client is configured with a client_secret, generate a special error message.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Output info message when PKCE without client_secret used on confidential client
* removes the special error message
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* General missing/invalid client_secret message on token endpoint
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
Co-authored-by: Tadeusz Magura-Witkowski <tadeuszmw@gmail.com>
Co-authored-by: Martin Heide <martin.heide@faro.com>
Co-authored-by: M. Heide <66078329+heidemn-faro@users.noreply.github.com>
2020-10-26 16:03:40 +05:30
|
|
|
|
|
|
|
CodeChallenge string `json:"code_challenge,omitempty"`
|
|
|
|
CodeChallengeMethod string `json:"code_challenge_method,omitempty"`
|
2016-07-26 01:30:28 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
// AuthRequestList is a list of AuthRequests.
|
|
|
|
type AuthRequestList struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ListMeta `json:"metadata,omitempty"`
|
|
|
|
AuthRequests []AuthRequest `json:"items"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func toStorageAuthRequest(req AuthRequest) storage.AuthRequest {
|
|
|
|
a := storage.AuthRequest{
|
|
|
|
ID: req.ObjectMeta.Name,
|
|
|
|
ClientID: req.ClientID,
|
|
|
|
ResponseTypes: req.ResponseTypes,
|
|
|
|
Scopes: req.Scopes,
|
|
|
|
RedirectURI: req.RedirectURI,
|
|
|
|
Nonce: req.Nonce,
|
|
|
|
State: req.State,
|
|
|
|
ForceApprovalPrompt: req.ForceApprovalPrompt,
|
2016-09-15 05:08:12 +05:30
|
|
|
LoggedIn: req.LoggedIn,
|
2016-07-26 01:30:28 +05:30
|
|
|
ConnectorID: req.ConnectorID,
|
2019-04-18 19:48:50 +05:30
|
|
|
ConnectorData: req.ConnectorData,
|
2016-07-26 01:30:28 +05:30
|
|
|
Expiry: req.Expiry,
|
2016-09-15 05:08:12 +05:30
|
|
|
Claims: toStorageClaims(req.Claims),
|
PKCE implementation (#1784)
* Basic implementation of PKCE
Signed-off-by: Tadeusz Magura-Witkowski <tadeuszmw@gmail.com>
* @mfmarche on 24 Feb: when code_verifier is set, don't check client_secret
In PKCE flow, no client_secret is used, so the check for a valid client_secret
would always fail.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* @deric on 16 Jun: return invalid_grant when wrong code_verifier
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Enforce PKCE flow on /token when PKCE flow was started on /auth
Also dissallow PKCE on /token, when PKCE flow was not started on /auth
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* fixed error messages when mixed PKCE/no PKCE flow.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* server_test.go: Added PKCE error cases on /token endpoint
* Added test for invalid_grant, when wrong code_verifier is sent
* Added test for mixed PKCE / no PKCE auth flows.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* cleanup: extracted method checkErrorResponse and type TestDefinition
* fixed connector being overwritten
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* /token endpoint: skip client_secret verification only for grand type authorization_code with PKCE extension
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Allow "Authorization" header in CORS handlers
* Adds "Authorization" to the default CORS headers{"Accept", "Accept-Language", "Content-Language", "Origin"}
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Add "code_challenge_methods_supported" to discovery endpoint
discovery endpoint /dex/.well-known/openid-configuration
now has the following entry:
"code_challenge_methods_supported": [
"S256",
"plain"
]
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Updated tests (mixed-up comments), added a PKCE test
* @asoorm added test that checks if downgrade to "plain" on /token endpoint
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* remove redefinition of providedCodeVerifier, fixed spelling (#6)
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
Signed-off-by: Bernd Eckstein <HEllRZA@users.noreply.github.com>
* Rename struct CodeChallenge to PKCE
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* PKCE: Check clientSecret when available
In authorization_code flow with PKCE, allow empty client_secret on /auth and /token endpoints. But check the client_secret when it is given.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Enable PKCE with public: true
dex configuration public on staticClients now enables the following behavior in PKCE:
- Public: false, PKCE will always check client_secret. This means PKCE in it's natural form is disabled.
- Public: true, PKCE is enabled. It will only check client_secret if the client has sent one. But it allows the code flow if the client didn't sent one.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Redirect error on unsupported code_challenge_method
- Check for unsupported code_challenge_method after redirect uri is validated, and use newErr() to return the error.
- Add PKCE tests to oauth2_test.go
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Reverted go.mod and go.sum to the state of master
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Don't omit client secret check for PKCE
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Allow public clients (e.g. with PKCE) to have redirect URIs configured
Signed-off-by: Martin Heide <martin.heide@faro.com>
* Remove "Authorization" as Accepted Headers on CORS, small fixes
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Revert "Allow public clients (e.g. with PKCE) to have redirect URIs configured"
This reverts commit b6e297b78537dc44cd3e1374f0b4d34bf89404ac.
Signed-off-by: Martin Heide <martin.heide@faro.com>
* PKCE on client_secret client error message
* When connecting to the token endpoint with PKCE without client_secret, but the client is configured with a client_secret, generate a special error message.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Output info message when PKCE without client_secret used on confidential client
* removes the special error message
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* General missing/invalid client_secret message on token endpoint
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
Co-authored-by: Tadeusz Magura-Witkowski <tadeuszmw@gmail.com>
Co-authored-by: Martin Heide <martin.heide@faro.com>
Co-authored-by: M. Heide <66078329+heidemn-faro@users.noreply.github.com>
2020-10-26 16:03:40 +05:30
|
|
|
PKCE: storage.PKCE{
|
|
|
|
CodeChallenge: req.CodeChallenge,
|
|
|
|
CodeChallengeMethod: req.CodeChallengeMethod,
|
|
|
|
},
|
2016-07-26 01:30:28 +05:30
|
|
|
}
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cli *client) fromStorageAuthRequest(a storage.AuthRequest) AuthRequest {
|
|
|
|
req := AuthRequest{
|
|
|
|
TypeMeta: k8sapi.TypeMeta{
|
|
|
|
Kind: kindAuthRequest,
|
2016-10-14 05:20:20 +05:30
|
|
|
APIVersion: cli.apiVersion,
|
2016-07-26 01:30:28 +05:30
|
|
|
},
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: a.ID,
|
|
|
|
Namespace: cli.namespace,
|
|
|
|
},
|
|
|
|
ClientID: a.ClientID,
|
|
|
|
ResponseTypes: a.ResponseTypes,
|
|
|
|
Scopes: a.Scopes,
|
|
|
|
RedirectURI: a.RedirectURI,
|
|
|
|
Nonce: a.Nonce,
|
|
|
|
State: a.State,
|
2016-09-15 05:08:12 +05:30
|
|
|
LoggedIn: a.LoggedIn,
|
2016-07-26 01:30:28 +05:30
|
|
|
ForceApprovalPrompt: a.ForceApprovalPrompt,
|
|
|
|
ConnectorID: a.ConnectorID,
|
2019-04-18 19:48:50 +05:30
|
|
|
ConnectorData: a.ConnectorData,
|
2016-07-26 01:30:28 +05:30
|
|
|
Expiry: a.Expiry,
|
2016-09-15 05:08:12 +05:30
|
|
|
Claims: fromStorageClaims(a.Claims),
|
PKCE implementation (#1784)
* Basic implementation of PKCE
Signed-off-by: Tadeusz Magura-Witkowski <tadeuszmw@gmail.com>
* @mfmarche on 24 Feb: when code_verifier is set, don't check client_secret
In PKCE flow, no client_secret is used, so the check for a valid client_secret
would always fail.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* @deric on 16 Jun: return invalid_grant when wrong code_verifier
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Enforce PKCE flow on /token when PKCE flow was started on /auth
Also dissallow PKCE on /token, when PKCE flow was not started on /auth
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* fixed error messages when mixed PKCE/no PKCE flow.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* server_test.go: Added PKCE error cases on /token endpoint
* Added test for invalid_grant, when wrong code_verifier is sent
* Added test for mixed PKCE / no PKCE auth flows.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* cleanup: extracted method checkErrorResponse and type TestDefinition
* fixed connector being overwritten
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* /token endpoint: skip client_secret verification only for grand type authorization_code with PKCE extension
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Allow "Authorization" header in CORS handlers
* Adds "Authorization" to the default CORS headers{"Accept", "Accept-Language", "Content-Language", "Origin"}
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Add "code_challenge_methods_supported" to discovery endpoint
discovery endpoint /dex/.well-known/openid-configuration
now has the following entry:
"code_challenge_methods_supported": [
"S256",
"plain"
]
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Updated tests (mixed-up comments), added a PKCE test
* @asoorm added test that checks if downgrade to "plain" on /token endpoint
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* remove redefinition of providedCodeVerifier, fixed spelling (#6)
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
Signed-off-by: Bernd Eckstein <HEllRZA@users.noreply.github.com>
* Rename struct CodeChallenge to PKCE
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* PKCE: Check clientSecret when available
In authorization_code flow with PKCE, allow empty client_secret on /auth and /token endpoints. But check the client_secret when it is given.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Enable PKCE with public: true
dex configuration public on staticClients now enables the following behavior in PKCE:
- Public: false, PKCE will always check client_secret. This means PKCE in it's natural form is disabled.
- Public: true, PKCE is enabled. It will only check client_secret if the client has sent one. But it allows the code flow if the client didn't sent one.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Redirect error on unsupported code_challenge_method
- Check for unsupported code_challenge_method after redirect uri is validated, and use newErr() to return the error.
- Add PKCE tests to oauth2_test.go
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Reverted go.mod and go.sum to the state of master
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Don't omit client secret check for PKCE
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Allow public clients (e.g. with PKCE) to have redirect URIs configured
Signed-off-by: Martin Heide <martin.heide@faro.com>
* Remove "Authorization" as Accepted Headers on CORS, small fixes
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Revert "Allow public clients (e.g. with PKCE) to have redirect URIs configured"
This reverts commit b6e297b78537dc44cd3e1374f0b4d34bf89404ac.
Signed-off-by: Martin Heide <martin.heide@faro.com>
* PKCE on client_secret client error message
* When connecting to the token endpoint with PKCE without client_secret, but the client is configured with a client_secret, generate a special error message.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Output info message when PKCE without client_secret used on confidential client
* removes the special error message
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* General missing/invalid client_secret message on token endpoint
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
Co-authored-by: Tadeusz Magura-Witkowski <tadeuszmw@gmail.com>
Co-authored-by: Martin Heide <martin.heide@faro.com>
Co-authored-by: M. Heide <66078329+heidemn-faro@users.noreply.github.com>
2020-10-26 16:03:40 +05:30
|
|
|
CodeChallenge: a.PKCE.CodeChallenge,
|
|
|
|
CodeChallengeMethod: a.PKCE.CodeChallengeMethod,
|
2016-07-26 01:30:28 +05:30
|
|
|
}
|
|
|
|
return req
|
|
|
|
}
|
|
|
|
|
2016-10-06 04:34:48 +05:30
|
|
|
// Password is a mirrored struct from the stroage with JSON struct tags and
|
|
|
|
// Kubernetes type metadata.
|
|
|
|
type Password struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ObjectMeta `json:"metadata,omitempty"`
|
|
|
|
|
|
|
|
// The Kubernetes name is actually an encoded version of this value.
|
|
|
|
//
|
|
|
|
// This field is IMMUTABLE. Do not change.
|
|
|
|
Email string `json:"email,omitempty"`
|
|
|
|
|
|
|
|
Hash []byte `json:"hash,omitempty"`
|
|
|
|
Username string `json:"username,omitempty"`
|
|
|
|
UserID string `json:"userID,omitempty"`
|
|
|
|
}
|
|
|
|
|
2016-11-17 04:27:27 +05:30
|
|
|
// PasswordList is a list of Passwords.
|
|
|
|
type PasswordList struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ListMeta `json:"metadata,omitempty"`
|
|
|
|
Passwords []Password `json:"items"`
|
|
|
|
}
|
|
|
|
|
2016-10-06 04:34:48 +05:30
|
|
|
func (cli *client) fromStoragePassword(p storage.Password) Password {
|
|
|
|
email := strings.ToLower(p.Email)
|
|
|
|
return Password{
|
|
|
|
TypeMeta: k8sapi.TypeMeta{
|
|
|
|
Kind: kindPassword,
|
2016-10-14 05:20:20 +05:30
|
|
|
APIVersion: cli.apiVersion,
|
2016-10-06 04:34:48 +05:30
|
|
|
},
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
2016-10-28 04:25:23 +05:30
|
|
|
Name: cli.idToName(email),
|
2016-10-06 04:34:48 +05:30
|
|
|
Namespace: cli.namespace,
|
|
|
|
},
|
|
|
|
Email: email,
|
|
|
|
Hash: p.Hash,
|
|
|
|
Username: p.Username,
|
|
|
|
UserID: p.UserID,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func toStoragePassword(p Password) storage.Password {
|
|
|
|
return storage.Password{
|
|
|
|
Email: p.Email,
|
|
|
|
Hash: p.Hash,
|
|
|
|
Username: p.Username,
|
|
|
|
UserID: p.UserID,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-26 01:30:28 +05:30
|
|
|
// AuthCode is a mirrored struct from storage with JSON struct tags and
|
|
|
|
// Kubernetes type metadata.
|
|
|
|
type AuthCode struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ObjectMeta `json:"metadata,omitempty"`
|
|
|
|
|
|
|
|
ClientID string `json:"clientID"`
|
|
|
|
Scopes []string `json:"scopes,omitempty"`
|
|
|
|
RedirectURI string `json:"redirectURI"`
|
|
|
|
|
|
|
|
Nonce string `json:"nonce,omitempty"`
|
|
|
|
State string `json:"state,omitempty"`
|
|
|
|
|
2016-08-03 10:27:36 +05:30
|
|
|
Claims Claims `json:"claims,omitempty"`
|
2016-08-03 09:44:24 +05:30
|
|
|
|
|
|
|
ConnectorID string `json:"connectorID,omitempty"`
|
|
|
|
ConnectorData []byte `json:"connectorData,omitempty"`
|
2016-07-26 01:30:28 +05:30
|
|
|
|
|
|
|
Expiry time.Time `json:"expiry"`
|
PKCE implementation (#1784)
* Basic implementation of PKCE
Signed-off-by: Tadeusz Magura-Witkowski <tadeuszmw@gmail.com>
* @mfmarche on 24 Feb: when code_verifier is set, don't check client_secret
In PKCE flow, no client_secret is used, so the check for a valid client_secret
would always fail.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* @deric on 16 Jun: return invalid_grant when wrong code_verifier
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Enforce PKCE flow on /token when PKCE flow was started on /auth
Also dissallow PKCE on /token, when PKCE flow was not started on /auth
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* fixed error messages when mixed PKCE/no PKCE flow.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* server_test.go: Added PKCE error cases on /token endpoint
* Added test for invalid_grant, when wrong code_verifier is sent
* Added test for mixed PKCE / no PKCE auth flows.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* cleanup: extracted method checkErrorResponse and type TestDefinition
* fixed connector being overwritten
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* /token endpoint: skip client_secret verification only for grand type authorization_code with PKCE extension
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Allow "Authorization" header in CORS handlers
* Adds "Authorization" to the default CORS headers{"Accept", "Accept-Language", "Content-Language", "Origin"}
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Add "code_challenge_methods_supported" to discovery endpoint
discovery endpoint /dex/.well-known/openid-configuration
now has the following entry:
"code_challenge_methods_supported": [
"S256",
"plain"
]
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Updated tests (mixed-up comments), added a PKCE test
* @asoorm added test that checks if downgrade to "plain" on /token endpoint
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* remove redefinition of providedCodeVerifier, fixed spelling (#6)
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
Signed-off-by: Bernd Eckstein <HEllRZA@users.noreply.github.com>
* Rename struct CodeChallenge to PKCE
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* PKCE: Check clientSecret when available
In authorization_code flow with PKCE, allow empty client_secret on /auth and /token endpoints. But check the client_secret when it is given.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Enable PKCE with public: true
dex configuration public on staticClients now enables the following behavior in PKCE:
- Public: false, PKCE will always check client_secret. This means PKCE in it's natural form is disabled.
- Public: true, PKCE is enabled. It will only check client_secret if the client has sent one. But it allows the code flow if the client didn't sent one.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Redirect error on unsupported code_challenge_method
- Check for unsupported code_challenge_method after redirect uri is validated, and use newErr() to return the error.
- Add PKCE tests to oauth2_test.go
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Reverted go.mod and go.sum to the state of master
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Don't omit client secret check for PKCE
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Allow public clients (e.g. with PKCE) to have redirect URIs configured
Signed-off-by: Martin Heide <martin.heide@faro.com>
* Remove "Authorization" as Accepted Headers on CORS, small fixes
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Revert "Allow public clients (e.g. with PKCE) to have redirect URIs configured"
This reverts commit b6e297b78537dc44cd3e1374f0b4d34bf89404ac.
Signed-off-by: Martin Heide <martin.heide@faro.com>
* PKCE on client_secret client error message
* When connecting to the token endpoint with PKCE without client_secret, but the client is configured with a client_secret, generate a special error message.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Output info message when PKCE without client_secret used on confidential client
* removes the special error message
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* General missing/invalid client_secret message on token endpoint
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
Co-authored-by: Tadeusz Magura-Witkowski <tadeuszmw@gmail.com>
Co-authored-by: Martin Heide <martin.heide@faro.com>
Co-authored-by: M. Heide <66078329+heidemn-faro@users.noreply.github.com>
2020-10-26 16:03:40 +05:30
|
|
|
|
|
|
|
CodeChallenge string `json:"code_challenge,omitempty"`
|
|
|
|
CodeChallengeMethod string `json:"code_challenge_method,omitempty"`
|
2016-07-26 01:30:28 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
// AuthCodeList is a list of AuthCodes.
|
|
|
|
type AuthCodeList struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ListMeta `json:"metadata,omitempty"`
|
|
|
|
AuthCodes []AuthCode `json:"items"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cli *client) fromStorageAuthCode(a storage.AuthCode) AuthCode {
|
|
|
|
return AuthCode{
|
|
|
|
TypeMeta: k8sapi.TypeMeta{
|
|
|
|
Kind: kindAuthCode,
|
2016-10-14 05:20:20 +05:30
|
|
|
APIVersion: cli.apiVersion,
|
2016-07-26 01:30:28 +05:30
|
|
|
},
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: a.ID,
|
|
|
|
Namespace: cli.namespace,
|
|
|
|
},
|
PKCE implementation (#1784)
* Basic implementation of PKCE
Signed-off-by: Tadeusz Magura-Witkowski <tadeuszmw@gmail.com>
* @mfmarche on 24 Feb: when code_verifier is set, don't check client_secret
In PKCE flow, no client_secret is used, so the check for a valid client_secret
would always fail.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* @deric on 16 Jun: return invalid_grant when wrong code_verifier
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Enforce PKCE flow on /token when PKCE flow was started on /auth
Also dissallow PKCE on /token, when PKCE flow was not started on /auth
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* fixed error messages when mixed PKCE/no PKCE flow.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* server_test.go: Added PKCE error cases on /token endpoint
* Added test for invalid_grant, when wrong code_verifier is sent
* Added test for mixed PKCE / no PKCE auth flows.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* cleanup: extracted method checkErrorResponse and type TestDefinition
* fixed connector being overwritten
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* /token endpoint: skip client_secret verification only for grand type authorization_code with PKCE extension
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Allow "Authorization" header in CORS handlers
* Adds "Authorization" to the default CORS headers{"Accept", "Accept-Language", "Content-Language", "Origin"}
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Add "code_challenge_methods_supported" to discovery endpoint
discovery endpoint /dex/.well-known/openid-configuration
now has the following entry:
"code_challenge_methods_supported": [
"S256",
"plain"
]
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Updated tests (mixed-up comments), added a PKCE test
* @asoorm added test that checks if downgrade to "plain" on /token endpoint
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* remove redefinition of providedCodeVerifier, fixed spelling (#6)
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
Signed-off-by: Bernd Eckstein <HEllRZA@users.noreply.github.com>
* Rename struct CodeChallenge to PKCE
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* PKCE: Check clientSecret when available
In authorization_code flow with PKCE, allow empty client_secret on /auth and /token endpoints. But check the client_secret when it is given.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Enable PKCE with public: true
dex configuration public on staticClients now enables the following behavior in PKCE:
- Public: false, PKCE will always check client_secret. This means PKCE in it's natural form is disabled.
- Public: true, PKCE is enabled. It will only check client_secret if the client has sent one. But it allows the code flow if the client didn't sent one.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Redirect error on unsupported code_challenge_method
- Check for unsupported code_challenge_method after redirect uri is validated, and use newErr() to return the error.
- Add PKCE tests to oauth2_test.go
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Reverted go.mod and go.sum to the state of master
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Don't omit client secret check for PKCE
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Allow public clients (e.g. with PKCE) to have redirect URIs configured
Signed-off-by: Martin Heide <martin.heide@faro.com>
* Remove "Authorization" as Accepted Headers on CORS, small fixes
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Revert "Allow public clients (e.g. with PKCE) to have redirect URIs configured"
This reverts commit b6e297b78537dc44cd3e1374f0b4d34bf89404ac.
Signed-off-by: Martin Heide <martin.heide@faro.com>
* PKCE on client_secret client error message
* When connecting to the token endpoint with PKCE without client_secret, but the client is configured with a client_secret, generate a special error message.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Output info message when PKCE without client_secret used on confidential client
* removes the special error message
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* General missing/invalid client_secret message on token endpoint
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
Co-authored-by: Tadeusz Magura-Witkowski <tadeuszmw@gmail.com>
Co-authored-by: Martin Heide <martin.heide@faro.com>
Co-authored-by: M. Heide <66078329+heidemn-faro@users.noreply.github.com>
2020-10-26 16:03:40 +05:30
|
|
|
ClientID: a.ClientID,
|
|
|
|
RedirectURI: a.RedirectURI,
|
|
|
|
ConnectorID: a.ConnectorID,
|
|
|
|
ConnectorData: a.ConnectorData,
|
|
|
|
Nonce: a.Nonce,
|
|
|
|
Scopes: a.Scopes,
|
|
|
|
Claims: fromStorageClaims(a.Claims),
|
|
|
|
Expiry: a.Expiry,
|
|
|
|
CodeChallenge: a.PKCE.CodeChallenge,
|
|
|
|
CodeChallengeMethod: a.PKCE.CodeChallengeMethod,
|
2016-07-26 01:30:28 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func toStorageAuthCode(a AuthCode) storage.AuthCode {
|
|
|
|
return storage.AuthCode{
|
2019-04-18 19:48:50 +05:30
|
|
|
ID: a.ObjectMeta.Name,
|
|
|
|
ClientID: a.ClientID,
|
|
|
|
RedirectURI: a.RedirectURI,
|
|
|
|
ConnectorID: a.ConnectorID,
|
|
|
|
ConnectorData: a.ConnectorData,
|
|
|
|
Nonce: a.Nonce,
|
|
|
|
Scopes: a.Scopes,
|
|
|
|
Claims: toStorageClaims(a.Claims),
|
|
|
|
Expiry: a.Expiry,
|
PKCE implementation (#1784)
* Basic implementation of PKCE
Signed-off-by: Tadeusz Magura-Witkowski <tadeuszmw@gmail.com>
* @mfmarche on 24 Feb: when code_verifier is set, don't check client_secret
In PKCE flow, no client_secret is used, so the check for a valid client_secret
would always fail.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* @deric on 16 Jun: return invalid_grant when wrong code_verifier
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Enforce PKCE flow on /token when PKCE flow was started on /auth
Also dissallow PKCE on /token, when PKCE flow was not started on /auth
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* fixed error messages when mixed PKCE/no PKCE flow.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* server_test.go: Added PKCE error cases on /token endpoint
* Added test for invalid_grant, when wrong code_verifier is sent
* Added test for mixed PKCE / no PKCE auth flows.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* cleanup: extracted method checkErrorResponse and type TestDefinition
* fixed connector being overwritten
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* /token endpoint: skip client_secret verification only for grand type authorization_code with PKCE extension
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Allow "Authorization" header in CORS handlers
* Adds "Authorization" to the default CORS headers{"Accept", "Accept-Language", "Content-Language", "Origin"}
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Add "code_challenge_methods_supported" to discovery endpoint
discovery endpoint /dex/.well-known/openid-configuration
now has the following entry:
"code_challenge_methods_supported": [
"S256",
"plain"
]
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Updated tests (mixed-up comments), added a PKCE test
* @asoorm added test that checks if downgrade to "plain" on /token endpoint
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* remove redefinition of providedCodeVerifier, fixed spelling (#6)
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
Signed-off-by: Bernd Eckstein <HEllRZA@users.noreply.github.com>
* Rename struct CodeChallenge to PKCE
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* PKCE: Check clientSecret when available
In authorization_code flow with PKCE, allow empty client_secret on /auth and /token endpoints. But check the client_secret when it is given.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Enable PKCE with public: true
dex configuration public on staticClients now enables the following behavior in PKCE:
- Public: false, PKCE will always check client_secret. This means PKCE in it's natural form is disabled.
- Public: true, PKCE is enabled. It will only check client_secret if the client has sent one. But it allows the code flow if the client didn't sent one.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Redirect error on unsupported code_challenge_method
- Check for unsupported code_challenge_method after redirect uri is validated, and use newErr() to return the error.
- Add PKCE tests to oauth2_test.go
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Reverted go.mod and go.sum to the state of master
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Don't omit client secret check for PKCE
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Allow public clients (e.g. with PKCE) to have redirect URIs configured
Signed-off-by: Martin Heide <martin.heide@faro.com>
* Remove "Authorization" as Accepted Headers on CORS, small fixes
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Revert "Allow public clients (e.g. with PKCE) to have redirect URIs configured"
This reverts commit b6e297b78537dc44cd3e1374f0b4d34bf89404ac.
Signed-off-by: Martin Heide <martin.heide@faro.com>
* PKCE on client_secret client error message
* When connecting to the token endpoint with PKCE without client_secret, but the client is configured with a client_secret, generate a special error message.
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* Output info message when PKCE without client_secret used on confidential client
* removes the special error message
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
* General missing/invalid client_secret message on token endpoint
Signed-off-by: Bernd Eckstein <Bernd.Eckstein@faro.com>
Co-authored-by: Tadeusz Magura-Witkowski <tadeuszmw@gmail.com>
Co-authored-by: Martin Heide <martin.heide@faro.com>
Co-authored-by: M. Heide <66078329+heidemn-faro@users.noreply.github.com>
2020-10-26 16:03:40 +05:30
|
|
|
PKCE: storage.PKCE{
|
|
|
|
CodeChallenge: a.CodeChallenge,
|
|
|
|
CodeChallengeMethod: a.CodeChallengeMethod,
|
|
|
|
},
|
2016-07-26 01:30:28 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-03 10:27:36 +05:30
|
|
|
// RefreshToken is a mirrored struct from storage with JSON struct tags and
|
2016-07-26 01:30:28 +05:30
|
|
|
// Kubernetes type metadata.
|
2016-08-03 10:27:36 +05:30
|
|
|
type RefreshToken struct {
|
2016-07-26 01:30:28 +05:30
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ObjectMeta `json:"metadata,omitempty"`
|
|
|
|
|
2016-12-23 05:26:09 +05:30
|
|
|
CreatedAt time.Time
|
|
|
|
LastUsed time.Time
|
|
|
|
|
2016-07-26 01:30:28 +05:30
|
|
|
ClientID string `json:"clientID"`
|
|
|
|
Scopes []string `json:"scopes,omitempty"`
|
|
|
|
|
2016-12-23 05:26:09 +05:30
|
|
|
Token string `json:"token,omitempty"`
|
|
|
|
|
2016-07-26 01:30:28 +05:30
|
|
|
Nonce string `json:"nonce,omitempty"`
|
|
|
|
|
2017-01-10 04:31:29 +05:30
|
|
|
Claims Claims `json:"claims,omitempty"`
|
|
|
|
ConnectorID string `json:"connectorID,omitempty"`
|
|
|
|
ConnectorData []byte `json:"connectorData,omitempty"`
|
2016-07-26 01:30:28 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
// RefreshList is a list of refresh tokens.
|
|
|
|
type RefreshList struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ListMeta `json:"metadata,omitempty"`
|
2016-08-03 10:27:36 +05:30
|
|
|
RefreshTokens []RefreshToken `json:"items"`
|
2016-07-26 01:30:28 +05:30
|
|
|
}
|
|
|
|
|
2016-12-23 05:26:09 +05:30
|
|
|
func toStorageRefreshToken(r RefreshToken) storage.RefreshToken {
|
|
|
|
return storage.RefreshToken{
|
2019-04-18 19:48:50 +05:30
|
|
|
ID: r.ObjectMeta.Name,
|
|
|
|
Token: r.Token,
|
|
|
|
CreatedAt: r.CreatedAt,
|
|
|
|
LastUsed: r.LastUsed,
|
|
|
|
ClientID: r.ClientID,
|
|
|
|
ConnectorID: r.ConnectorID,
|
|
|
|
ConnectorData: r.ConnectorData,
|
|
|
|
Scopes: r.Scopes,
|
|
|
|
Nonce: r.Nonce,
|
|
|
|
Claims: toStorageClaims(r.Claims),
|
2016-12-23 05:26:09 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cli *client) fromStorageRefreshToken(r storage.RefreshToken) RefreshToken {
|
|
|
|
return RefreshToken{
|
|
|
|
TypeMeta: k8sapi.TypeMeta{
|
|
|
|
Kind: kindRefreshToken,
|
|
|
|
APIVersion: cli.apiVersion,
|
|
|
|
},
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: r.ID,
|
|
|
|
Namespace: cli.namespace,
|
|
|
|
},
|
2019-04-18 19:48:50 +05:30
|
|
|
Token: r.Token,
|
|
|
|
CreatedAt: r.CreatedAt,
|
|
|
|
LastUsed: r.LastUsed,
|
|
|
|
ClientID: r.ClientID,
|
|
|
|
ConnectorID: r.ConnectorID,
|
|
|
|
ConnectorData: r.ConnectorData,
|
|
|
|
Scopes: r.Scopes,
|
|
|
|
Nonce: r.Nonce,
|
|
|
|
Claims: fromStorageClaims(r.Claims),
|
2016-12-23 05:26:09 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-26 01:30:28 +05:30
|
|
|
// Keys is a mirrored struct from storage with JSON struct tags and Kubernetes
|
|
|
|
// type metadata.
|
|
|
|
type Keys struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ObjectMeta `json:"metadata,omitempty"`
|
|
|
|
|
|
|
|
// Key for creating and verifying signatures. These may be nil.
|
|
|
|
SigningKey *jose.JSONWebKey `json:"signingKey,omitempty"`
|
|
|
|
SigningKeyPub *jose.JSONWebKey `json:"signingKeyPub,omitempty"`
|
|
|
|
// Old signing keys which have been rotated but can still be used to validate
|
|
|
|
// existing signatures.
|
|
|
|
VerificationKeys []storage.VerificationKey `json:"verificationKeys,omitempty"`
|
|
|
|
|
|
|
|
// The next time the signing key will rotate.
|
|
|
|
//
|
|
|
|
// For caching purposes, implementations MUST NOT update keys before this time.
|
|
|
|
NextRotation time.Time `json:"nextRotation"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cli *client) fromStorageKeys(keys storage.Keys) Keys {
|
|
|
|
return Keys{
|
|
|
|
TypeMeta: k8sapi.TypeMeta{
|
|
|
|
Kind: kindKeys,
|
2016-10-14 05:20:20 +05:30
|
|
|
APIVersion: cli.apiVersion,
|
2016-07-26 01:30:28 +05:30
|
|
|
},
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: keysName,
|
|
|
|
Namespace: cli.namespace,
|
|
|
|
},
|
|
|
|
SigningKey: keys.SigningKey,
|
|
|
|
SigningKeyPub: keys.SigningKeyPub,
|
|
|
|
VerificationKeys: keys.VerificationKeys,
|
|
|
|
NextRotation: keys.NextRotation,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func toStorageKeys(keys Keys) storage.Keys {
|
|
|
|
return storage.Keys{
|
|
|
|
SigningKey: keys.SigningKey,
|
|
|
|
SigningKeyPub: keys.SigningKeyPub,
|
|
|
|
VerificationKeys: keys.VerificationKeys,
|
|
|
|
NextRotation: keys.NextRotation,
|
|
|
|
}
|
|
|
|
}
|
2017-02-01 05:41:59 +05:30
|
|
|
|
|
|
|
// OfflineSessions is a mirrored struct from storage with JSON struct tags and Kubernetes
|
|
|
|
// type metadata.
|
|
|
|
type OfflineSessions struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ObjectMeta `json:"metadata,omitempty"`
|
|
|
|
|
2018-01-30 02:45:01 +05:30
|
|
|
UserID string `json:"userID,omitempty"`
|
|
|
|
ConnID string `json:"connID,omitempty"`
|
|
|
|
Refresh map[string]*storage.RefreshTokenRef `json:"refresh,omitempty"`
|
|
|
|
ConnectorData []byte `json:"connectorData,omitempty"`
|
2017-02-01 05:41:59 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
func (cli *client) fromStorageOfflineSessions(o storage.OfflineSessions) OfflineSessions {
|
|
|
|
return OfflineSessions{
|
|
|
|
TypeMeta: k8sapi.TypeMeta{
|
|
|
|
Kind: kindOfflineSessions,
|
|
|
|
APIVersion: cli.apiVersion,
|
|
|
|
},
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: cli.offlineTokenName(o.UserID, o.ConnID),
|
|
|
|
Namespace: cli.namespace,
|
|
|
|
},
|
2018-01-30 02:45:01 +05:30
|
|
|
UserID: o.UserID,
|
|
|
|
ConnID: o.ConnID,
|
|
|
|
Refresh: o.Refresh,
|
|
|
|
ConnectorData: o.ConnectorData,
|
2017-02-01 05:41:59 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func toStorageOfflineSessions(o OfflineSessions) storage.OfflineSessions {
|
2017-02-24 08:50:50 +05:30
|
|
|
s := storage.OfflineSessions{
|
2018-01-30 02:45:01 +05:30
|
|
|
UserID: o.UserID,
|
|
|
|
ConnID: o.ConnID,
|
|
|
|
Refresh: o.Refresh,
|
|
|
|
ConnectorData: o.ConnectorData,
|
2017-02-01 05:41:59 +05:30
|
|
|
}
|
2017-02-24 08:50:50 +05:30
|
|
|
if s.Refresh == nil {
|
|
|
|
// Server code assumes this will be non-nil.
|
|
|
|
s.Refresh = make(map[string]*storage.RefreshTokenRef)
|
|
|
|
}
|
|
|
|
return s
|
2017-02-01 05:41:59 +05:30
|
|
|
}
|
2017-03-23 22:29:33 +05:30
|
|
|
|
|
|
|
// Connector is a mirrored struct from storage with JSON struct tags and Kubernetes
|
|
|
|
// type metadata.
|
|
|
|
type Connector struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ObjectMeta `json:"metadata,omitempty"`
|
|
|
|
|
2020-04-07 14:32:44 +05:30
|
|
|
ID string `json:"id,omitempty"`
|
|
|
|
Type string `json:"type,omitempty"`
|
|
|
|
Name string `json:"name,omitempty"`
|
2017-03-23 22:29:33 +05:30
|
|
|
// Config holds connector specific configuration information
|
|
|
|
Config []byte `json:"config,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cli *client) fromStorageConnector(c storage.Connector) Connector {
|
|
|
|
return Connector{
|
|
|
|
TypeMeta: k8sapi.TypeMeta{
|
|
|
|
Kind: kindConnector,
|
|
|
|
APIVersion: cli.apiVersion,
|
|
|
|
},
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: c.ID,
|
|
|
|
Namespace: cli.namespace,
|
|
|
|
},
|
2020-04-07 14:32:44 +05:30
|
|
|
ID: c.ID,
|
|
|
|
Type: c.Type,
|
|
|
|
Name: c.Name,
|
|
|
|
Config: c.Config,
|
2017-03-23 22:29:33 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func toStorageConnector(c Connector) storage.Connector {
|
|
|
|
return storage.Connector{
|
|
|
|
ID: c.ID,
|
|
|
|
Type: c.Type,
|
|
|
|
Name: c.Name,
|
2020-04-07 14:32:44 +05:30
|
|
|
ResourceVersion: c.ObjectMeta.ResourceVersion,
|
2017-03-23 22:29:33 +05:30
|
|
|
Config: c.Config,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ConnectorList is a list of Connectors.
|
|
|
|
type ConnectorList struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ListMeta `json:"metadata,omitempty"`
|
|
|
|
Connectors []Connector `json:"items"`
|
|
|
|
}
|
2020-01-16 21:25:07 +05:30
|
|
|
|
|
|
|
// DeviceRequest is a mirrored struct from storage with JSON struct tags and
|
|
|
|
// Kubernetes type metadata.
|
|
|
|
type DeviceRequest struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ObjectMeta `json:"metadata,omitempty"`
|
|
|
|
|
2020-02-04 20:37:18 +05:30
|
|
|
DeviceCode string `json:"device_code,omitempty"`
|
|
|
|
ClientID string `json:"client_id,omitempty"`
|
|
|
|
ClientSecret string `json:"client_secret,omitempty"`
|
|
|
|
Scopes []string `json:"scopes,omitempty"`
|
|
|
|
Expiry time.Time `json:"expiry"`
|
2020-01-16 21:25:07 +05:30
|
|
|
}
|
|
|
|
|
2020-10-18 02:32:29 +05:30
|
|
|
// DeviceRequestList is a list of DeviceRequests.
|
2020-01-16 21:25:07 +05:30
|
|
|
type DeviceRequestList struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ListMeta `json:"metadata,omitempty"`
|
|
|
|
DeviceRequests []DeviceRequest `json:"items"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cli *client) fromStorageDeviceRequest(a storage.DeviceRequest) DeviceRequest {
|
|
|
|
req := DeviceRequest{
|
|
|
|
TypeMeta: k8sapi.TypeMeta{
|
|
|
|
Kind: kindDeviceRequest,
|
|
|
|
APIVersion: cli.apiVersion,
|
|
|
|
},
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: strings.ToLower(a.UserCode),
|
|
|
|
Namespace: cli.namespace,
|
|
|
|
},
|
2020-02-04 20:37:18 +05:30
|
|
|
DeviceCode: a.DeviceCode,
|
|
|
|
ClientID: a.ClientID,
|
|
|
|
ClientSecret: a.ClientSecret,
|
|
|
|
Scopes: a.Scopes,
|
|
|
|
Expiry: a.Expiry,
|
2020-01-16 21:25:07 +05:30
|
|
|
}
|
|
|
|
return req
|
|
|
|
}
|
|
|
|
|
2020-01-29 00:44:30 +05:30
|
|
|
func toStorageDeviceRequest(req DeviceRequest) storage.DeviceRequest {
|
|
|
|
return storage.DeviceRequest{
|
2020-02-04 20:37:18 +05:30
|
|
|
UserCode: strings.ToUpper(req.ObjectMeta.Name),
|
|
|
|
DeviceCode: req.DeviceCode,
|
|
|
|
ClientID: req.ClientID,
|
|
|
|
ClientSecret: req.ClientSecret,
|
|
|
|
Scopes: req.Scopes,
|
|
|
|
Expiry: req.Expiry,
|
2020-01-29 00:44:30 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-16 21:25:07 +05:30
|
|
|
// DeviceToken is a mirrored struct from storage with JSON struct tags and
|
|
|
|
// Kubernetes type metadata.
|
|
|
|
type DeviceToken struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ObjectMeta `json:"metadata,omitempty"`
|
|
|
|
|
2020-01-29 00:44:30 +05:30
|
|
|
Status string `json:"status,omitempty"`
|
|
|
|
Token string `json:"token,omitempty"`
|
|
|
|
Expiry time.Time `json:"expiry"`
|
|
|
|
LastRequestTime time.Time `json:"last_request"`
|
|
|
|
PollIntervalSeconds int `json:"poll_interval"`
|
2020-01-16 21:25:07 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
// DeviceTokenList is a list of DeviceTokens.
|
|
|
|
type DeviceTokenList struct {
|
|
|
|
k8sapi.TypeMeta `json:",inline"`
|
|
|
|
k8sapi.ListMeta `json:"metadata,omitempty"`
|
|
|
|
DeviceTokens []DeviceToken `json:"items"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cli *client) fromStorageDeviceToken(t storage.DeviceToken) DeviceToken {
|
|
|
|
req := DeviceToken{
|
|
|
|
TypeMeta: k8sapi.TypeMeta{
|
|
|
|
Kind: kindDeviceToken,
|
|
|
|
APIVersion: cli.apiVersion,
|
|
|
|
},
|
|
|
|
ObjectMeta: k8sapi.ObjectMeta{
|
|
|
|
Name: t.DeviceCode,
|
|
|
|
Namespace: cli.namespace,
|
|
|
|
},
|
2020-01-29 00:44:30 +05:30
|
|
|
Status: t.Status,
|
|
|
|
Token: t.Token,
|
|
|
|
Expiry: t.Expiry,
|
|
|
|
LastRequestTime: t.LastRequestTime,
|
|
|
|
PollIntervalSeconds: t.PollIntervalSeconds,
|
2020-01-16 21:25:07 +05:30
|
|
|
}
|
|
|
|
return req
|
|
|
|
}
|
2020-01-27 21:05:37 +05:30
|
|
|
|
|
|
|
func toStorageDeviceToken(t DeviceToken) storage.DeviceToken {
|
|
|
|
return storage.DeviceToken{
|
2020-01-29 00:44:30 +05:30
|
|
|
DeviceCode: t.ObjectMeta.Name,
|
|
|
|
Status: t.Status,
|
|
|
|
Token: t.Token,
|
|
|
|
Expiry: t.Expiry,
|
|
|
|
LastRequestTime: t.LastRequestTime,
|
|
|
|
PollIntervalSeconds: t.PollIntervalSeconds,
|
2020-01-27 21:05:37 +05:30
|
|
|
}
|
|
|
|
}
|