Skip to content

Commit fd1668e

Browse files
committed
add flag to set client-id for device-flow
1 parent 75bf1b4 commit fd1668e

File tree

1 file changed

+52
-6
lines changed

1 file changed

+52
-6
lines changed

cmd/src/login.go

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@ import (
77
"io"
88
"os"
99
"strings"
10+
"time"
1011

1112
"github.com/sourcegraph/src-cli/internal/api"
1213
"github.com/sourcegraph/src-cli/internal/cmderrors"
14+
"github.com/sourcegraph/src-cli/internal/oauthdevice"
1315
)
1416

1517
func init() {
1618
usage := `'src login' helps you authenticate 'src' to access a Sourcegraph instance with your user credentials.
1719
1820
Usage:
1921
20-
src login SOURCEGRAPH_URL
22+
src login [flags] SOURCEGRAPH_URL
2123
2224
Examples:
2325
@@ -32,6 +34,11 @@ Examples:
3234
Use OAuth device flow to authenticate:
3335
3436
$ src login --device-flow https://sourcegraph.com
37+
38+
39+
Override the default client id used during device flow when authenticating:
40+
41+
$ src login --device-flow https://sourcegraph.com --client-id sgo_my_own_client_id
3542
`
3643

3744
flagSet := flag.NewFlagSet("login", flag.ExitOnError)
@@ -41,7 +48,9 @@ Examples:
4148
}
4249

4350
var (
44-
apiFlags = api.NewFlags(flagSet)
51+
apiFlags = api.NewFlags(flagSet)
52+
useDeviceFlow = flagSet.Bool("device-flow", false, "Use OAuth device flow to obtain an access token interactively")
53+
OAuthClientID = flagSet.String("client-id", oauthdevice.DefaultClientID, "Client ID to use with OAuth device flow. Will use the predefined src cli client ID if not specified.")
4554
)
4655

4756
handler := func(args []string) error {
@@ -56,9 +65,21 @@ Examples:
5665
return cmderrors.Usage("expected exactly one argument: the Sourcegraph URL, or SRC_ENDPOINT to be set")
5766
}
5867

68+
if *OAuthClientID == "" {
69+
return cmderrors.Usage("no value specified for client-id")
70+
}
71+
5972
client := cfg.apiClient(apiFlags, io.Discard)
6073

61-
return loginCmd(context.Background(), cfg, client, endpoint, os.Stdout)
74+
return loginCmd(context.Background(), loginParams{
75+
cfg: cfg,
76+
client: client,
77+
endpoint: endpoint,
78+
out: os.Stdout,
79+
useDeviceFlow: *useDeviceFlow,
80+
apiFlags: apiFlags,
81+
deviceFlowClient: oauthdevice.NewClient(*OAuthClientID),
82+
})
6283
}
6384

6485
commands = append(commands, &command{
@@ -68,8 +89,21 @@ Examples:
6889
})
6990
}
7091

71-
func loginCmd(ctx context.Context, cfg *config, client api.Client, endpointArg string, out io.Writer) error {
72-
endpointArg = cleanEndpoint(endpointArg)
92+
type loginParams struct {
93+
cfg *config
94+
client api.Client
95+
endpoint string
96+
out io.Writer
97+
useDeviceFlow bool
98+
apiFlags *api.Flags
99+
deviceFlowClient oauthdevice.Client
100+
}
101+
102+
func loginCmd(ctx context.Context, p loginParams) error {
103+
endpointArg := cleanEndpoint(p.endpoint)
104+
cfg := p.cfg
105+
client := p.client
106+
out := p.out
73107

74108
printProblem := func(problem string) {
75109
fmt.Fprintf(out, "❌ Problem: %s\n", problem)
@@ -90,7 +124,19 @@ func loginCmd(ctx context.Context, cfg *config, client api.Client, endpointArg s
90124

91125
noToken := cfg.AccessToken == ""
92126
endpointConflict := endpointArg != cfg.Endpoint
93-
if noToken || endpointConflict {
127+
128+
if p.useDeviceFlow {
129+
token, err := runDeviceFlow(ctx, endpointArg, out, p.deviceFlowClient)
130+
if err != nil {
131+
printProblem(fmt.Sprintf("Device flow authentication failed: %s", err))
132+
fmt.Fprintln(out, createAccessTokenMessage)
133+
return cmderrors.ExitCode1
134+
}
135+
136+
cfg.AccessToken = token
137+
cfg.Endpoint = endpointArg
138+
client = cfg.apiClient(p.apiFlags, out)
139+
} else if noToken || endpointConflict {
94140
fmt.Fprintln(out)
95141
switch {
96142
case noToken:

0 commit comments

Comments
 (0)