Device flow token code exchange (#2)
* Added /device/token handler with associated business logic and storage tests. Perform user code exchange, flag the device code as complete. Moved device handler code into its own file for cleanliness. Cleanup * Removed PKCE code * Rate limiting for /device/token endpoint based on ietf standards * Configurable Device expiry Signed-off-by: justin-slowik <justin.slowik@thermofisher.com>
This commit is contained in:
committed by
justin-slowik
parent
0d1a0e4129
commit
9bbdc721d5
@@ -570,6 +570,13 @@ func (c *conn) CreateDeviceRequest(d storage.DeviceRequest) error {
|
||||
return c.txnCreate(ctx, keyID(deviceRequestPrefix, d.UserCode), fromStorageDeviceRequest(d))
|
||||
}
|
||||
|
||||
func (c *conn) GetDeviceRequest(userCode string) (r storage.DeviceRequest, err error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultStorageTimeout)
|
||||
defer cancel()
|
||||
err = c.getKey(ctx, keyID(deviceRequestPrefix, userCode), &r)
|
||||
return r, err
|
||||
}
|
||||
|
||||
func (c *conn) listDeviceRequests(ctx context.Context) (requests []DeviceRequest, err error) {
|
||||
res, err := c.db.Get(ctx, deviceRequestPrefix, clientv3.WithPrefix())
|
||||
if err != nil {
|
||||
@@ -612,3 +619,21 @@ func (c *conn) listDeviceTokens(ctx context.Context) (deviceTokens []DeviceToken
|
||||
}
|
||||
return deviceTokens, nil
|
||||
}
|
||||
|
||||
func (c *conn) UpdateDeviceToken(deviceCode string, updater func(old storage.DeviceToken) (storage.DeviceToken, error)) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultStorageTimeout)
|
||||
defer cancel()
|
||||
return c.txnUpdate(ctx, keyID(deviceTokenPrefix, deviceCode), func(currentValue []byte) ([]byte, error) {
|
||||
var current DeviceToken
|
||||
if len(currentValue) > 0 {
|
||||
if err := json.Unmarshal(currentValue, ¤t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
updated, err := updater(toStorageDeviceToken(current))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(fromStorageDeviceToken(updated))
|
||||
})
|
||||
}
|
||||
|
@@ -219,38 +219,51 @@ func toStorageOfflineSessions(o OfflineSessions) storage.OfflineSessions {
|
||||
|
||||
// DeviceRequest is a mirrored struct from storage with JSON struct tags
|
||||
type DeviceRequest struct {
|
||||
UserCode string `json:"user_code"`
|
||||
DeviceCode string `json:"device_code"`
|
||||
ClientID string `json:"client_id"`
|
||||
Scopes []string `json:"scopes"`
|
||||
PkceVerifier string `json:"pkce_verifier"`
|
||||
Expiry time.Time `json:"expiry"`
|
||||
UserCode string `json:"user_code"`
|
||||
DeviceCode string `json:"device_code"`
|
||||
ClientID string `json:"client_id"`
|
||||
Scopes []string `json:"scopes"`
|
||||
Expiry time.Time `json:"expiry"`
|
||||
}
|
||||
|
||||
func fromStorageDeviceRequest(d storage.DeviceRequest) DeviceRequest {
|
||||
return DeviceRequest{
|
||||
UserCode: d.UserCode,
|
||||
DeviceCode: d.DeviceCode,
|
||||
ClientID: d.ClientID,
|
||||
Scopes: d.Scopes,
|
||||
PkceVerifier: d.PkceVerifier,
|
||||
Expiry: d.Expiry,
|
||||
UserCode: d.UserCode,
|
||||
DeviceCode: d.DeviceCode,
|
||||
ClientID: d.ClientID,
|
||||
Scopes: d.Scopes,
|
||||
Expiry: d.Expiry,
|
||||
}
|
||||
}
|
||||
|
||||
// DeviceToken is a mirrored struct from storage with JSON struct tags
|
||||
type DeviceToken struct {
|
||||
DeviceCode string `json:"device_code"`
|
||||
Status string `json:"status"`
|
||||
Token string `json:"token"`
|
||||
Expiry time.Time `json:"expiry"`
|
||||
DeviceCode string `json:"device_code"`
|
||||
Status string `json:"status"`
|
||||
Token string `json:"token"`
|
||||
Expiry time.Time `json:"expiry"`
|
||||
LastRequestTime time.Time `json:"last_request"`
|
||||
PollIntervalSeconds int `json:"poll_interval"`
|
||||
}
|
||||
|
||||
func fromStorageDeviceToken(t storage.DeviceToken) DeviceToken {
|
||||
return DeviceToken{
|
||||
DeviceCode: t.DeviceCode,
|
||||
Status: t.Status,
|
||||
Token: t.Token,
|
||||
Expiry: t.Expiry,
|
||||
DeviceCode: t.DeviceCode,
|
||||
Status: t.Status,
|
||||
Token: t.Token,
|
||||
Expiry: t.Expiry,
|
||||
LastRequestTime: t.LastRequestTime,
|
||||
PollIntervalSeconds: t.PollIntervalSeconds,
|
||||
}
|
||||
}
|
||||
|
||||
func toStorageDeviceToken(t DeviceToken) storage.DeviceToken {
|
||||
return storage.DeviceToken{
|
||||
DeviceCode: t.DeviceCode,
|
||||
Status: t.Status,
|
||||
Token: t.Token,
|
||||
Expiry: t.Expiry,
|
||||
LastRequestTime: t.LastRequestTime,
|
||||
PollIntervalSeconds: t.PollIntervalSeconds,
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user