feat: allow external auth providers to expose extra metadata (#10157)

This commit is contained in:
Kyle Carberry
2023-10-09 23:02:16 -05:00
committed by GitHub
parent 3eb9a43190
commit 9c098b218f
12 changed files with 144 additions and 30 deletions

View File

@ -1,10 +1,13 @@
package cli
import (
"encoding/json"
"os/signal"
"golang.org/x/xerrors"
"github.com/tidwall/gjson"
"github.com/coder/coder/v2/cli/clibase"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk/agentsdk"
@ -25,7 +28,7 @@ func (r *RootCmd) externalAuth() *clibase.Cmd {
}
func (r *RootCmd) externalAuthAccessToken() *clibase.Cmd {
var silent bool
var extra string
return &clibase.Cmd{
Use: "access-token <provider>",
Short: "Print auth for an external provider",
@ -45,12 +48,16 @@ else
fi
`,
},
example{
Description: "Obtain an extra property of an access token for additional metadata.",
Command: "coder external-auth access-token slack --extra \"authed_user.id\"",
},
),
Options: clibase.OptionSet{{
Name: "Silent",
Flag: "s",
Description: "Do not print the URL or access token.",
Value: clibase.BoolOf(&silent),
Name: "Extra",
Flag: "extra",
Description: "Extract a field from the \"extra\" properties of the OAuth token.",
Value: clibase.StringOf(&extra),
}},
Handler: func(inv *clibase.Invocation) error {
@ -64,27 +71,38 @@ fi
return xerrors.Errorf("create agent client: %w", err)
}
token, err := client.ExternalAuth(ctx, agentsdk.ExternalAuthRequest{
extAuth, err := client.ExternalAuth(ctx, agentsdk.ExternalAuthRequest{
ID: inv.Args[0],
})
if err != nil {
return xerrors.Errorf("get external auth token: %w", err)
}
if !silent {
if token.URL != "" {
_, err = inv.Stdout.Write([]byte(token.URL))
} else {
_, err = inv.Stdout.Write([]byte(token.AccessToken))
}
if extAuth.URL != "" {
_, err = inv.Stdout.Write([]byte(extAuth.URL))
if err != nil {
return err
}
}
if token.URL != "" {
return cliui.Canceled
}
if extra != "" {
if extAuth.TokenExtra == nil {
return xerrors.Errorf("no extra properties found for token")
}
data, err := json.Marshal(extAuth.TokenExtra)
if err != nil {
return xerrors.Errorf("marshal extra properties: %w", err)
}
result := gjson.GetBytes(data, extra)
_, err = inv.Stdout.Write([]byte(result.String()))
if err != nil {
return err
}
return nil
}
_, err = inv.Stdout.Write([]byte(extAuth.AccessToken))
if err != nil {
return err
}
return nil
},
}

View File

@ -46,4 +46,22 @@ func TestExternalAuth(t *testing.T) {
clitest.Start(t, inv)
pty.ExpectMatch("bananas")
})
t.Run("SuccessWithExtra", func(t *testing.T) {
t.Parallel()
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
httpapi.Write(context.Background(), w, http.StatusOK, agentsdk.ExternalAuthResponse{
AccessToken: "bananas",
TokenExtra: map[string]interface{}{
"hey": "there",
},
})
}))
t.Cleanup(srv.Close)
url := srv.URL
inv, _ := clitest.New(t, "--agent-url", url, "external-auth", "access-token", "github", "--extra", "hey")
pty := ptytest.New(t)
inv.Stdout = pty.Output()
clitest.Start(t, inv)
pty.ExpectMatch("there")
})
}

View File

@ -19,10 +19,14 @@ USAGE:
echo "Please authenticate with GitHub:"
echo $OUTPUT
fi
- Obtain an extra property of an access token for additional metadata.:
$ coder external-auth access-token slack --extra "authed_user.id"
OPTIONS:
--s bool
Do not print the URL or access token.
--extra string
Extract a field from the "extra" properties of the OAuth token.
———
Run `coder --help` for a list of global options.