@@ -27,6 +27,7 @@ import (
2727 "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/transport"
2828 "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/usage"
2929 "github.com/spf13/cobra"
30+ "go.mongodb.org/atlas-sdk/v20250312006/auth/clientcredentials"
3031 atlas "go.mongodb.org/atlas/mongodbatlas"
3132)
3233
@@ -41,8 +42,14 @@ type ConfigDeleter interface {
4142 SetOrgID (string )
4243 SetPublicAPIKey (string )
4344 SetPrivateAPIKey (string )
45+ SetClientID (string )
46+ SetClientSecret (string )
4447 AuthType () config.AuthMechanism
4548 PublicAPIKey () string
49+ ClientID () string
50+ ClientSecret () string
51+ AccessTokenSubject () (string , error )
52+ RefreshToken () string
4653 Save () error
4754}
4855
@@ -53,32 +60,56 @@ type Revoker interface {
5360type logoutOpts struct {
5461 * cli.DeleteOpts
5562 cli.DefaultSetterOpts
56- OutWriter io.Writer
57- config ConfigDeleter
58- flow Revoker
59- keepConfig bool
63+ OutWriter io.Writer
64+ config ConfigDeleter
65+ flow Revoker
66+ keepConfig bool
67+ revokeServiceAccountToken func () error
6068}
6169
62- func (opts * logoutOpts ) initFlow () error {
70+ func (opts * logoutOpts ) initFlow (ctx context. Context ) error {
6371 var err error
6472 client := http .DefaultClient
6573 client .Transport = transport .Default ()
6674 opts .flow , err = oauth .FlowWithConfig (config .Default (), client )
75+ opts .revokeServiceAccountToken = func () error {
76+ return revokeServiceAccountToken (ctx , opts .config .ClientID (), opts .config .ClientSecret ())
77+ }
6778 return err
6879}
6980
81+ func revokeServiceAccountToken (ctx context.Context , clientID , clientSecret string ) error {
82+ cfg := clientcredentials .NewConfig (clientID , clientSecret )
83+ if config .OpsManagerURL () != "" {
84+ // TokenURL and RevokeURL points to "https://cloud.mongodb.com/api/oauth/<token/revoke>". Modify TokenURL and RevokeURL if OpsManagerURL does not point to cloud.mongodb.com
85+ cfg .TokenURL = config .OpsManagerURL () + clientcredentials .TokenAPIPath
86+ cfg .RevokeURL = config .OpsManagerURL () + clientcredentials .RevokeAPIPath
87+ }
88+ token , err := cfg .Token (ctx )
89+ if err != nil {
90+ return err
91+ }
92+ return cfg .RevokeToken (ctx , token )
93+ }
94+
7095func (opts * logoutOpts ) Run (ctx context.Context ) error {
7196 if ! opts .Confirm {
7297 return nil
7398 }
7499
75100 switch opts .config .AuthType () {
76- case config .ServiceAccount , config . UserAccount :
101+ case config .UserAccount :
77102 if _ , err := opts .flow .RevokeToken (ctx , config .RefreshToken (), "refresh_token" ); err != nil {
78103 return err
79104 }
80105 opts .config .SetAccessToken ("" )
81106 opts .config .SetRefreshToken ("" )
107+ case config .ServiceAccount :
108+ if err := opts .revokeServiceAccountToken (); err != nil {
109+ return err
110+ }
111+ opts .config .SetClientID ("" )
112+ opts .config .SetClientSecret ("" )
82113 case config .APIKeys :
83114 opts .config .SetPublicAPIKey ("" )
84115 opts .config .SetPrivateAPIKey ("" )
@@ -87,6 +118,8 @@ func (opts *logoutOpts) Run(ctx context.Context) error {
87118 opts .config .SetPrivateAPIKey ("" )
88119 opts .config .SetAccessToken ("" )
89120 opts .config .SetRefreshToken ("" )
121+ opts .config .SetClientID ("" )
122+ opts .config .SetClientSecret ("" )
90123 }
91124
92125 opts .config .SetProjectID ("" )
@@ -122,7 +155,7 @@ func LogoutBuilder() *cobra.Command {
122155
123156 // Only initialize OAuth flow if we have OAuth-based auth
124157 if opts .config .AuthType () == config .UserAccount || opts .config .AuthType () == config .ServiceAccount {
125- return opts .initFlow ()
158+ return opts .initFlow (cmd . Context () )
126159 }
127160
128161 return nil
@@ -135,13 +168,16 @@ func LogoutBuilder() *cobra.Command {
135168 case config .APIKeys :
136169 entry = opts .config .PublicAPIKey ()
137170 message = "Are you sure you want to log out of account with public API key %s?"
138- case config .ServiceAccount , config .UserAccount :
139- entry , err = config .AccessTokenSubject ()
171+ case config .ServiceAccount :
172+ entry = opts .config .ClientID ()
173+ message = "Are you sure you want to log out of service account %s?"
174+ case config .UserAccount :
175+ entry , err = opts .config .AccessTokenSubject ()
140176 if err != nil {
141177 return err
142178 }
143179
144- if config .RefreshToken () == "" {
180+ if opts . config .RefreshToken () == "" {
145181 return ErrUnauthenticated
146182 }
147183
0 commit comments