Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OCM-4968: offline token deprecation messaging #680

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions cmd/ocm/delete/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"github.com/openshift-online/ocm-cli/cmd/ocm/delete/upgradepolicy"
"github.com/openshift-online/ocm-cli/cmd/ocm/delete/user"
"github.com/openshift-online/ocm-cli/pkg/arguments"
"github.com/openshift-online/ocm-cli/pkg/config"
"github.com/openshift-online/ocm-cli/pkg/dump"
"github.com/openshift-online/ocm-cli/pkg/ocm"
"github.com/openshift-online/ocm-cli/pkg/urls"
Expand Down Expand Up @@ -132,25 +131,6 @@ func run(cmd *cobra.Command, argv []string) error {
return fmt.Errorf("can't print body: %w", err)
}

// Load the configuration file:
cfg, err := config.Load()
if err != nil {
return fmt.Errorf("can't load config file: %w", err)
}
if cfg == nil {
return fmt.Errorf("not logged in, run the 'login' command")
}

// Save the configuration:
cfg.AccessToken, cfg.RefreshToken, err = connection.Tokens()
if err != nil {
return fmt.Errorf("can't get tokens: %w", err)
}
err = config.Save(cfg)
if err != nil {
return fmt.Errorf("can't save config file: %w", err)
}

// Bye:
if status >= 400 {
os.Exit(1)
Expand Down
20 changes: 0 additions & 20 deletions cmd/ocm/get/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"github.com/spf13/cobra"

"github.com/openshift-online/ocm-cli/pkg/arguments"
"github.com/openshift-online/ocm-cli/pkg/config"
"github.com/openshift-online/ocm-cli/pkg/dump"
"github.com/openshift-online/ocm-cli/pkg/ocm"
"github.com/openshift-online/ocm-cli/pkg/urls"
Expand Down Expand Up @@ -61,15 +60,6 @@ func run(cmd *cobra.Command, argv []string) error {
return fmt.Errorf("Could not create URI: %v", err)
}

// Load the configuration file:
cfg, err := config.Load()
if err != nil {
return fmt.Errorf("Can't load config file: %v", err)
}
if cfg == nil {
return fmt.Errorf("Not logged in, run the 'login' command")
}

// Create the client for the OCM API:
connection, err := ocm.NewConnection().Build()
if err != nil {
Expand Down Expand Up @@ -111,16 +101,6 @@ func run(cmd *cobra.Command, argv []string) error {
return fmt.Errorf("Can't print body: %v", err)
}

// Save the configuration:
cfg.AccessToken, cfg.RefreshToken, err = connection.Tokens()
if err != nil {
return fmt.Errorf("Can't get tokens: %v", err)
}
err = config.Save(cfg)
if err != nil {
return fmt.Errorf("Can't save config file: %v", err)
}

// Bye:
if status >= 400 {
os.Exit(1)
Expand Down
12 changes: 3 additions & 9 deletions cmd/ocm/login/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,20 +329,14 @@ func run(cmd *cobra.Command, argv []string) error {
cfg.Password = args.password
cfg.Insecure = args.insecure

// Create a connection and get the token to verify that the crendentials are correct:
connection, err := ocm.NewConnection().Config(cfg).Build()
// Create a connection to verify that the credentials are correct:
_, err = ocm.NewConnection().Config(cfg).Build()
if err != nil {
return fmt.Errorf("Can't create connection: %v", err)
}
accessToken, refreshToken, err := connection.Tokens()
if err != nil {
return fmt.Errorf("Can't get token: %v", err)
}

// Save the configuration, but clear the user name and password before unless we have
// clear the user name and password before unless we have
// explicitly been asked to store them persistently:
cfg.AccessToken = accessToken
cfg.RefreshToken = refreshToken
if !args.persistent {
cfg.User = ""
cfg.Password = ""
Expand Down
15 changes: 0 additions & 15 deletions cmd/ocm/patch/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"github.com/spf13/cobra"

"github.com/openshift-online/ocm-cli/pkg/arguments"
"github.com/openshift-online/ocm-cli/pkg/config"
"github.com/openshift-online/ocm-cli/pkg/dump"
"github.com/openshift-online/ocm-cli/pkg/ocm"
"github.com/openshift-online/ocm-cli/pkg/urls"
Expand Down Expand Up @@ -92,20 +91,6 @@ func run(cmd *cobra.Command, argv []string) error {
if err != nil {
return fmt.Errorf("Can't print body: %v", err)
}
// Load the configuration file:
cfg, err := config.Load()
if err != nil {
return fmt.Errorf("Can't load config file: %v", err)
}
// Save the configuration:
cfg.AccessToken, cfg.RefreshToken, err = connection.Tokens()
if err != nil {
return fmt.Errorf("Can't get tokens: %v", err)
}
err = config.Save(cfg)
if err != nil {
return fmt.Errorf("Can't save config file: %v", err)
}

// Bye:
if status >= 400 {
Expand Down
16 changes: 0 additions & 16 deletions cmd/ocm/post/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"github.com/spf13/cobra"

"github.com/openshift-online/ocm-cli/pkg/arguments"
"github.com/openshift-online/ocm-cli/pkg/config"
"github.com/openshift-online/ocm-cli/pkg/dump"
"github.com/openshift-online/ocm-cli/pkg/ocm"
"github.com/openshift-online/ocm-cli/pkg/urls"
Expand Down Expand Up @@ -93,21 +92,6 @@ func run(cmd *cobra.Command, argv []string) error {
return fmt.Errorf("Can't print body: %v", err)
}

// Load the configuration file:
cfg, err := config.Load()
if err != nil {
return fmt.Errorf("Can't load config file: %v", err)
}
// Save the configuration:
cfg.AccessToken, cfg.RefreshToken, err = connection.Tokens()
if err != nil {
return fmt.Errorf("Can't get tokens: %v", err)
}
err = config.Save(cfg)
if err != nil {
return fmt.Errorf("Can't save config file: %v", err)
}

// Bye:
if status >= 400 {
os.Exit(1)
Expand Down
37 changes: 16 additions & 21 deletions cmd/ocm/token/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,21 +107,21 @@ func run(cmd *cobra.Command, argv []string) error {
}
defer connection.Close()

var accessToken string
var refreshToken string
// Load the configuration file:
cfg, err := config.Load()
if err != nil {
return fmt.Errorf("Can't load config file: %v", err)
}

var accessToken = cfg.AccessToken
var refreshToken = cfg.RefreshToken

if args.generate {
// Get new tokens:
accessToken, refreshToken, err = connection.Tokens(15 * time.Minute)
if err != nil {
return fmt.Errorf("Can't get new tokens: %v", err)
}
} else {
// Get the tokens:
accessToken, refreshToken, err = connection.Tokens()
if err != nil {
return fmt.Errorf("Can't get token: %v", err)
}
}

// Select the token according to the options:
Expand Down Expand Up @@ -170,20 +170,15 @@ func run(cmd *cobra.Command, argv []string) error {
fmt.Fprintf(os.Stdout, "%s\n", selectedToken)
}

// Load the configuration file:
cfg, err := config.Load()
if err != nil {
return fmt.Errorf("Can't load config file: %v", err)
}

// Save the configuration:
cfg.AccessToken = accessToken
cfg.RefreshToken = refreshToken
err = config.Save(cfg)
if err != nil {
return fmt.Errorf("Can't save config file: %v", err)
if args.generate {
// Save the configuration:
cfg.AccessToken = accessToken
cfg.RefreshToken = refreshToken
err = config.Save(cfg)
if err != nil {
return fmt.Errorf("Can't save config file: %v", err)
}
}

// Bye:
return nil
}
64 changes: 63 additions & 1 deletion pkg/ocm/connection-builder/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ package connection

import (
"fmt"
"strings"

"github.com/golang-jwt/jwt/v4"
"github.com/golang/glog"
sdk "github.com/openshift-online/ocm-sdk-go"
"github.com/openshift-online/ocm-sdk-go/logging"
Expand Down Expand Up @@ -114,7 +116,32 @@ func (b *ConnectionBuilder) Build() (result *sdk.Connection, err error) {
}

// Create the connection:
return builder.Build()
conn, err := builder.Build()
if err != nil {
return conn, err
}

// Token management:
accessToken, refreshToken, err := conn.Tokens()
if err != nil {
return nil, fmt.Errorf("Can't get tokens: %v", err)
}

// Only execute if the refresh token has changed. This helps limit warnings for users
// to only on login and when their refresh token is cycled by SSO instead of on every command.
if b.cfg.RefreshToken != refreshToken {
offlineTokenDeprecationWarning(refreshToken)
}

b.cfg.AccessToken = accessToken
b.cfg.RefreshToken = refreshToken

err = config.Save(b.cfg)
if err != nil {
return nil, fmt.Errorf("Can't save config file: %v", err)
}

return conn, nil
}

func (b *ConnectionBuilder) initConnectionBuilderFromConfig() *sdk.ConnectionBuilder {
Expand Down Expand Up @@ -178,3 +205,38 @@ func (b *ConnectionBuilder) getAgent() string {
}
return "OCM-CLI/" + info.Version
}

// Prints a deprecation warning if tokens have changed and the new refresh token contains the 'offline_access' scope
// Swallow and log errors as this is a non-essential warning that should not block the user
func offlineTokenDeprecationWarning(refreshToken string) {
const offlineTokenDeprecationMessage = "Logging in with offline tokens is being deprecated and will no longer " +
"be maintained or enhanced. Instead, log in with --use-auth-code or --use-device-code. See 'ocm login --help' " +
"for usage. Learn more about deprecating offline tokens via https://console.redhat.com/openshift/token"

parser := new(jwt.Parser)
token, _, err := parser.ParseUnverified(refreshToken, jwt.MapClaims{})
if err != nil {
if debug.Enabled() {
fmt.Printf("Failed to parse refresh token for deprecation warning: %v\n", err)
}
return
}
claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
if debug.Enabled() {
fmt.Printf("Failed to get claims from refresh token for deprecation warning: %v\n", err)
}
return
}
scopes, ok := claims["scope"].(string)
if !ok {
if debug.Enabled() {
fmt.Printf("Failed to get scopes from refresh token for deprecation warning: %v\n", err)
}
return
}
if strings.Contains(scopes, "offline_access") {
fmt.Println(offlineTokenDeprecationMessage)
return
}
}
Loading