Skip to content

Commit

Permalink
chore: removing MAS-SSO tokens (#1634)
Browse files Browse the repository at this point in the history
* fix: refactor codebase to remove mas-sso tokens

* fix: documentation for command
  • Loading branch information
wtrocki authored Jul 11, 2022
1 parent 21d5dbe commit 29bcafa
Show file tree
Hide file tree
Showing 23 changed files with 70 additions and 520 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ go run ./cmd/rhoas kafka create "test" --provider=aws --region=us-east-1
To use QA environment we need to login using following arguments

```shell
rhoas login --api-gateway=stage --mas-auth-url=stage
rhoas login --api-gateway=stage
```

### Development features
Expand Down
2 changes: 0 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ REPOSITORY_NAME ?= "app-services-cli"

CONSTANTS_URL ?= "https://console.redhat.com/apps/application-services/service-constants.json"
SSO_REDIRECT_PATH ?= "sso-redhat-callback"
MAS_SSO_REDIRECT_PATH ?= "mas-sso-callback"
BUILD_SOURCE ?= "local"

# see pkg/cmdutil/constants.go
Expand All @@ -22,7 +21,6 @@ GO_LDFLAGS := -X github.com/redhat-developer/app-services-cli/internal/build.Dyn
GO_LDFLAGS := -X github.com/redhat-developer/app-services-cli/internal/build.DefaultPageSize=$(DEFAULT_PAGE_SIZE) $(GO_LDFLAGS)
GO_LDFLAGS := -X github.com/redhat-developer/app-services-cli/internal/build.DefaultPageNumber=$(DEFAULT_PAGE_NUMBER) $(GO_LDFLAGS)
GO_LDFLAGS := -X github.com/redhat-developer/app-services-cli/internal/build.SSORedirectPath=$(SSO_REDIRECT_PATH) $(GO_LDFLAGS)
GO_LDFLAGS := -X github.com/redhat-developer/app-services-cli/internal/build.MASSSORedirectPath=$(MAS_SSO_REDIRECT_PATH) $(GO_LDFLAGS)
GO_LDFLAGS := -X github.com/redhat-developer/app-services-cli/internal/build.BuildSource=$(BUILD_SOURCE) $(GO_LDFLAGS)

BUILDFLAGS :=
Expand Down
2 changes: 1 addition & 1 deletion docs/commands/rhoas_login.md

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

5 changes: 0 additions & 5 deletions internal/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ var (
// SSORedirectPath is the default SSO redirect path
SSORedirectPath = "sso-redhat-callback"

// MASSSORedirectPath is the default MAS-SSO redirect path
MASSSORedirectPath = "mas-sso-callback"

// BuildSource is a unique key which indicates the infrastructure on which the binary was built
BuildSource = "local"
)
Expand All @@ -63,8 +60,6 @@ var (
DefaultLoginTimeout = 60 * time.Second
OfflineTokenURL = ConsoleURL + "/openshift/token"
ProductionAuthURL = "https://sso.redhat.com/auth/realms/redhat-external"
ProductionMasAuthURL = "https://identity.api.openshift.com/auth/realms/rhoas"
StagingMasAuthURL = "https://identity.api.stage.openshift.com/auth/realms/rhoas"
)

func init() {
Expand Down
2 changes: 0 additions & 2 deletions internal/mockutil/mockutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ func NewConnectionMock(conn *kcconnection.Connection, apiClient *kafkamgmtclient

cfg.AccessToken = ""
cfg.RefreshToken = ""
cfg.MasAccessToken = ""
cfg.MasRefreshToken = ""

return conn.Config.Save(cfg)
},
Expand Down
33 changes: 3 additions & 30 deletions pkg/cmd/login/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"github.com/redhat-developer/app-services-cli/pkg/core/ioutil/spinner"
"github.com/redhat-developer/app-services-cli/pkg/core/localize"
"github.com/redhat-developer/app-services-cli/pkg/core/logging"
"github.com/redhat-developer/app-services-cli/pkg/shared/connection"
"github.com/redhat-developer/app-services-cli/pkg/shared/connection/kcconnection"
"github.com/redhat-developer/app-services-cli/pkg/shared/factory"

Expand Down Expand Up @@ -45,15 +44,6 @@ var authURLAliases = map[string]string{
"stage": build.ProductionAuthURL,
}

// When the value of the `--mas-auth-url` option is one of the keys of this map it will be replaced by the
// corresponding value.
var masAuthURLAliases = map[string]string{
"production": build.ProductionMasAuthURL,
"prod": build.ProductionMasAuthURL,
"staging": build.StagingMasAuthURL,
"stage": build.StagingMasAuthURL,
}

type options struct {
Config config.IConfig
Logger logging.Logger
Expand All @@ -64,7 +54,7 @@ type options struct {

url string
authURL string
masAuthURL string
deprecatedUrl string
clientID string
scopes []string
insecureSkipTLSVerify bool
Expand Down Expand Up @@ -106,7 +96,7 @@ func NewLoginCmd(f *factory.Factory) *cobra.Command {
cmd.Flags().BoolVar(&opts.insecureSkipTLSVerify, "insecure", false, opts.localizer.MustLocalize("login.flag.insecure"))
cmd.Flags().StringVar(&opts.clientID, "client-id", build.DefaultClientID, opts.localizer.MustLocalize("login.flag.clientId"))
cmd.Flags().StringVar(&opts.authURL, "auth-url", build.ProductionAuthURL, opts.localizer.MustLocalize("login.flag.authUrl"))
cmd.Flags().StringVar(&opts.masAuthURL, "mas-auth-url", build.ProductionMasAuthURL, opts.localizer.MustLocalize("login.flag.masAuthUrl"))
cmd.Flags().StringVar(&opts.deprecatedUrl, "mas-auth-url", "", opts.localizer.MustLocalize("login.flag.masAuthUrl"))
cmd.Flags().BoolVar(&opts.printURL, "print-sso-url", false, opts.localizer.MustLocalize("login.flag.printSsoUrl"))
cmd.Flags().StringArrayVar(&opts.scopes, "scope", kcconnection.DefaultScopes, opts.localizer.MustLocalize("login.flag.scope"))
cmd.Flags().StringVarP(&opts.offlineToken, "token", "t", "", opts.localizer.MustLocalize("login.flag.token", localize.NewEntry("OfflineTokenURL", build.OfflineTokenURL)))
Expand All @@ -127,12 +117,6 @@ func runLogin(opts *options) (err error) {
}
opts.authURL = authURL.String()

masAuthURL, err := getURLFromAlias(opts.masAuthURL, masAuthURLAliases, opts.localizer)
if err != nil {
return err
}
opts.masAuthURL = masAuthURL.String()

// log in to SSO
spinner := spinner.New(opts.IO.ErrOut, opts.localizer)
spinner.SetLocalizedSuffix("login.log.info.loggingIn")
Expand All @@ -158,16 +142,11 @@ func runLogin(opts *options) (err error) {
RedirectPath: build.SSORedirectPath,
}

masSsoCfg := &login.SSOConfig{
AuthURL: masAuthURL,
RedirectPath: build.MASSSORedirectPath,
}

// Creating a global context with timeout
ctx, cancel := context.WithTimeout(context.Background(), build.DefaultLoginTimeout)
defer cancel()

if err = loginExec.Execute(ctx, ssoCfg, masSsoCfg, gatewayURL.String()); err != nil {
if err = loginExec.Execute(ctx, ssoCfg, gatewayURL.String()); err != nil {
spinner.Stop()
opts.Logger.Info()
if errors.Is(err, context.DeadlineExceeded) {
Expand Down Expand Up @@ -196,7 +175,6 @@ func runLogin(opts *options) (err error) {
cfg.Insecure = opts.insecureSkipTLSVerify
cfg.ClientID = opts.clientID
cfg.AuthURL = opts.authURL
cfg.MasAuthURL = opts.masAuthURL
cfg.Scopes = opts.scopes

if err = opts.Config.Save(cfg); err != nil {
Expand Down Expand Up @@ -229,18 +207,13 @@ func loginWithOfflineToken(opts *options) (err error) {
cfg.Insecure = opts.insecureSkipTLSVerify
cfg.ClientID = opts.clientID
cfg.AuthURL = opts.authURL
cfg.MasAuthURL = opts.masAuthURL
cfg.Scopes = opts.scopes
cfg.RefreshToken = opts.offlineToken
// remove MAS-SSO tokens, as this does not support token login
cfg.MasAccessToken = ""
cfg.MasRefreshToken = ""

if err = opts.Config.Save(cfg); err != nil {
return err
}

_, err = opts.Connection(connection.DefaultConfigSkipMasAuth)
return err
}

Expand Down
115 changes: 1 addition & 114 deletions pkg/core/auth/login/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ import (
"github.com/redhat-developer/app-services-cli/pkg/core/ioutil/iostreams"
"github.com/redhat-developer/app-services-cli/pkg/core/localize"
"github.com/redhat-developer/app-services-cli/pkg/core/logging"
"github.com/redhat-developer/app-services-cli/pkg/shared/hacks"

"github.com/coreos/go-oidc/v3/oidc"
"github.com/phayes/freeport"
"github.com/redhat-developer/app-services-cli/static"
"golang.org/x/oauth2"
)

Expand All @@ -38,37 +36,12 @@ type SSOConfig struct {
}

// Execute runs an Authorization Code flow login
// enabling the user to log in to SSO and MAS-SSO in succession
// https://tools.ietf.org/html/rfc6749#section-4.1
func (a *AuthorizationCodeGrant) Execute(ctx context.Context,
ssoCfg *SSOConfig, masSSOCfg *SSOConfig, apiUrl string) error {
ssoCfg *SSOConfig, apiUrl string) error {
if err := a.loginSSO(ctx, ssoCfg); err != nil {
return err
}

if !hacks.ShouldUseMasSSO(a.Logger, apiUrl) {
cfg, err := a.Config.Load()
if err != nil {
return err
}
cfg.MasAccessToken = ""
cfg.MasRefreshToken = ""
err = a.Config.Save(cfg)
if err != nil {
return err
}
return nil
}

masSSOHost := masSSOCfg.AuthURL.Host

a.Logger.Debug(a.Localizer.MustLocalize("login.log.info.loggingInMAS", localize.NewEntry("Host", masSSOHost)))
// log in to MAS-SSO
if err := a.loginMAS(ctx, masSSOCfg); err != nil {
return err
}
a.Logger.Debug(a.Localizer.MustLocalize("login.log.info.loggedInMAS", localize.NewEntry("Host", masSSOHost)))

return nil
}

Expand Down Expand Up @@ -123,8 +96,6 @@ func (a *AuthorizationCodeGrant) loginSSO(ctx context.Context, cfg *SSOConfig) e
http.Redirect(w, r, authCodeURL, http.StatusFound)
})

sm.Handle("/static/", createStaticHTTPHandler())

authURL, err := url.Parse(cfg.AuthURL.String())
if err != nil {
return err
Expand Down Expand Up @@ -158,85 +129,6 @@ func (a *AuthorizationCodeGrant) loginSSO(ctx context.Context, cfg *SSOConfig) e
return nil
}

// log in to MAS-SSO
func (a *AuthorizationCodeGrant) loginMAS(ctx context.Context, cfg *SSOConfig) error {
a.Logger.Debug("Logging into", cfg.AuthURL, "\n")

clientCtx, cancel := createClientContext(ctx, a.HTTPClient)
defer cancel()
provider, err := oidc.NewProvider(ctx, cfg.AuthURL.String())
if err != nil {
return err
}

redirectURL, redirectURLPort, err := createRedirectURL(cfg.RedirectPath)
if err != nil {
return err
}

oauthConfig := &oauth2.Config{
ClientID: a.ClientID,
Endpoint: provider.Endpoint(),
RedirectURL: redirectURL.String(),
Scopes: a.Scopes,
}

oidcConfig := &oidc.Config{
ClientID: a.ClientID,
}

// Configure PKCE challenge and verifier
// https://tools.ietf.org/html/rfc7636
verifier := provider.Verifier(oidcConfig)
state, _ := pkce.GenerateVerifier(128)
pkceCodeVerifier, err := pkce.GenerateVerifier(128)
if err != nil {
return err
}
pkceCodeChallenge := pkce.CreateChallenge(pkceCodeVerifier)

authCodeURL := oauthConfig.AuthCodeURL(state, *pkce.GetAuthCodeURLOptions(pkceCodeChallenge)...)
a.Logger.Debug("Opening Authorization URL:", authCodeURL)
a.Logger.Debug()

sm := http.NewServeMux()
server := http.Server{
Handler: sm,
Addr: redirectURL.Host,
}

sm.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, authCodeURL, http.StatusFound)
})

sm.Handle("/static/", createStaticHTTPHandler())

// HTTP handler for the redirect page
sm.Handle("/"+redirectURL.Path, &masRedirectPageHandler{
CancelContext: cancel,
Ctx: clientCtx,
Port: redirectURLPort,
Config: a.Config,
Logger: a.Logger,
AuthURL: cfg.AuthURL,
IO: a.IO,
ServerAddr: server.Addr,
Oauth2Config: oauthConfig,
State: state,
TokenVerifier: verifier,
Localizer: a.Localizer,
AuthOptions: []oauth2.AuthCodeOption{
oauth2.SetAuthURLParam("code_verifier", pkceCodeVerifier),
oauth2.SetAuthURLParam("grant_type", "authorization_code"),
},
})

a.openBrowser(authCodeURL, redirectURL)
a.startServer(clientCtx, &server)

return nil
}

func (a *AuthorizationCodeGrant) openBrowser(authCodeURL string, redirectURL *url.URL) {
if a.PrintURL {
a.Logger.Info(a.Localizer.MustLocalize("login.log.info.openSSOUrl"), "\n")
Expand Down Expand Up @@ -291,8 +183,3 @@ func (a *AuthorizationCodeGrant) printAuthURLFallback(authCodeURL string, redire
a.Logger.Debug("Error opening browser:", err, "\nPrinting Auth URL to console instead")
a.openBrowser(authCodeURL, redirectURL)
}

func createStaticHTTPHandler() http.Handler {
staticFs := http.FileServer(http.FS(static.ImagesFS()))
return http.StripPrefix("/static", staticFs)
}
Loading

0 comments on commit 29bcafa

Please sign in to comment.