Skip to content

Commit eac997c

Browse files
committed
create new func to avoid the bug on issue #61
1 parent adf5f73 commit eac997c

File tree

4 files changed

+93
-67
lines changed

4 files changed

+93
-67
lines changed

Diff for: examples_test.go

+16-15
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,30 @@
11
package oauth_test
22

33
import (
4-
"fmt"
5-
"os"
4+
"fmt"
5+
"os"
66

7-
"github.com/cli/oauth"
7+
"github.com/cli/oauth"
88
)
99

1010
// DetectFlow attempts to initiate OAuth Device flow with the server and falls back to OAuth Web
1111
// application flow if Device flow seems unsupported. This approach isn't strictly needed for
1212
// github.com, as its Device flow support is globally available, but it enables logging in to
1313
// self-hosted GitHub instances as well.
1414
func ExampleFlow_DetectFlow() {
15-
flow := &oauth.Flow{
16-
Host: oauth.GitHubHost("https://github.com"),
17-
ClientID: os.Getenv("OAUTH_CLIENT_ID"),
18-
ClientSecret: os.Getenv("OAUTH_CLIENT_SECRET"), // only applicable to web app flow
19-
CallbackURI: "http://127.0.0.1/callback", // only applicable to web app flow
20-
Scopes: []string{"repo", "read:org", "gist"},
21-
}
15+
host, err := oauth.NewGitHubHost("https://github.com")
16+
flow := &oauth.Flow{
17+
Host: host,
18+
ClientID: os.Getenv("OAUTH_CLIENT_ID"),
19+
ClientSecret: os.Getenv("OAUTH_CLIENT_SECRET"), // only applicable to web app flow
20+
CallbackURI: "http://127.0.0.1/callback", // only applicable to web app flow
21+
Scopes: []string{"repo", "read:org", "gist"},
22+
}
2223

23-
accessToken, err := flow.DetectFlow()
24-
if err != nil {
25-
panic(err)
26-
}
24+
accessToken, err := flow.DetectFlow()
25+
if err != nil {
26+
panic(err)
27+
}
2728

28-
fmt.Printf("Access token: %s\n", accessToken.Token)
29+
fmt.Printf("Access token: %s\n", accessToken.Token)
2930
}

Diff for: oauth.go

+64-50
Original file line numberDiff line numberDiff line change
@@ -3,77 +3,91 @@
33
package oauth
44

55
import (
6-
"errors"
7-
"fmt"
8-
"io"
9-
"net/http"
10-
"net/url"
6+
"errors"
7+
"fmt"
8+
"io"
9+
"net/http"
10+
"net/url"
11+
"strings"
1112

12-
"github.com/cli/oauth/api"
13-
"github.com/cli/oauth/device"
13+
"github.com/cli/oauth/api"
14+
"github.com/cli/oauth/device"
1415
)
1516

1617
type httpClient interface {
17-
PostForm(string, url.Values) (*http.Response, error)
18+
PostForm(string, url.Values) (*http.Response, error)
1819
}
1920

2021
// Host defines the endpoints used to authorize against an OAuth server.
2122
type Host struct {
22-
DeviceCodeURL string
23-
AuthorizeURL string
24-
TokenURL string
23+
DeviceCodeURL string
24+
AuthorizeURL string
25+
TokenURL string
26+
}
27+
28+
func NewGitHubHost(hostURL string) (*Host, error) {
29+
u, err := url.Parse(strings.TrimSpace(hostURL))
30+
if err != nil {
31+
return nil, err
32+
}
33+
34+
return &Host{
35+
DeviceCodeURL: fmt.Sprintf("%s://%s/login/device/code", u.Scheme, u.Host),
36+
AuthorizeURL: fmt.Sprintf("%s://%s/login/oauth/authorize", u.Scheme, u.Host),
37+
TokenURL: fmt.Sprintf("%s://%s/login/oauth/access_token", u.Scheme, u.Host),
38+
}, nil
2539
}
2640

2741
// GitHubHost constructs a Host from the given URL to a GitHub instance.
2842
func GitHubHost(hostURL string) *Host {
29-
u, _ := url.Parse(hostURL)
43+
u, _ := url.Parse(hostURL)
3044

31-
return &Host{
32-
DeviceCodeURL: fmt.Sprintf("%s://%s/login/device/code", u.Scheme, u.Host),
33-
AuthorizeURL: fmt.Sprintf("%s://%s/login/oauth/authorize", u.Scheme, u.Host),
34-
TokenURL: fmt.Sprintf("%s://%s/login/oauth/access_token", u.Scheme, u.Host),
35-
}
45+
return &Host{
46+
DeviceCodeURL: fmt.Sprintf("%s://%s/login/device/code", u.Scheme, u.Host),
47+
AuthorizeURL: fmt.Sprintf("%s://%s/login/oauth/authorize", u.Scheme, u.Host),
48+
TokenURL: fmt.Sprintf("%s://%s/login/oauth/access_token", u.Scheme, u.Host),
49+
}
3650
}
3751

3852
// Flow facilitates a single OAuth authorization flow.
3953
type Flow struct {
40-
// The hostname to authorize the app with.
41-
//
42-
// Deprecated: Use Host instead.
43-
Hostname string
44-
// Host configuration to authorize the app with.
45-
Host *Host
46-
// OAuth scopes to request from the user.
47-
Scopes []string
48-
// OAuth application ID.
49-
ClientID string
50-
// OAuth application secret. Only applicable in web application flow.
51-
ClientSecret string
52-
// The localhost URI for web application flow callback, e.g. "http://127.0.0.1/callback".
53-
CallbackURI string
54+
// The hostname to authorize the app with.
55+
//
56+
// Deprecated: Use Host instead.
57+
Hostname string
58+
// Host configuration to authorize the app with.
59+
Host *Host
60+
// OAuth scopes to request from the user.
61+
Scopes []string
62+
// OAuth application ID.
63+
ClientID string
64+
// OAuth application secret. Only applicable in web application flow.
65+
ClientSecret string
66+
// The localhost URI for web application flow callback, e.g. "http://127.0.0.1/callback".
67+
CallbackURI string
5468

55-
// Display a one-time code to the user. Receives the code and the browser URL as arguments. Defaults to printing the
56-
// code to the user on Stdout with instructions to copy the code and to press Enter to continue in their browser.
57-
DisplayCode func(string, string) error
58-
// Open a web browser at a URL. Defaults to opening the default system browser.
59-
BrowseURL func(string) error
60-
// Render an HTML page to the user upon completion of web application flow. The default is to
61-
// render a simple message that informs the user they can close the browser tab and return to the app.
62-
WriteSuccessHTML func(io.Writer)
69+
// Display a one-time code to the user. Receives the code and the browser URL as arguments. Defaults to printing the
70+
// code to the user on Stdout with instructions to copy the code and to press Enter to continue in their browser.
71+
DisplayCode func(string, string) error
72+
// Open a web browser at a URL. Defaults to opening the default system browser.
73+
BrowseURL func(string) error
74+
// Render an HTML page to the user upon completion of web application flow. The default is to
75+
// render a simple message that informs the user they can close the browser tab and return to the app.
76+
WriteSuccessHTML func(io.Writer)
6377

64-
// The HTTP client to use for API POST requests. Defaults to http.DefaultClient.
65-
HTTPClient httpClient
66-
// The stream to listen to keyboard input on. Defaults to os.Stdin.
67-
Stdin io.Reader
68-
// The stream to print UI messages to. Defaults to os.Stdout.
69-
Stdout io.Writer
78+
// The HTTP client to use for API POST requests. Defaults to http.DefaultClient.
79+
HTTPClient httpClient
80+
// The stream to listen to keyboard input on. Defaults to os.Stdin.
81+
Stdin io.Reader
82+
// The stream to print UI messages to. Defaults to os.Stdout.
83+
Stdout io.Writer
7084
}
7185

7286
// DetectFlow tries to perform Device flow first and falls back to Web application flow.
7387
func (oa *Flow) DetectFlow() (*api.AccessToken, error) {
74-
accessToken, err := oa.DeviceFlow()
75-
if errors.Is(err, device.ErrUnsupported) {
76-
return oa.WebAppFlow()
77-
}
78-
return accessToken, err
88+
accessToken, err := oa.DeviceFlow()
89+
if errors.Is(err, device.ErrUnsupported) {
90+
return oa.WebAppFlow()
91+
}
92+
return accessToken, err
7993
}

Diff for: oauth_device.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,15 @@ func (oa *Flow) DeviceFlow() (*api.AccessToken, error) {
2929
if stdout == nil {
3030
stdout = os.Stdout
3131
}
32+
3233
host := oa.Host
3334
if host == nil {
34-
host = GitHubHost("https://" + oa.Hostname)
35+
_, err := NewGitHubHost("https://" + oa.Hostname)
36+
if err != nil {
37+
return nil, fmt.Errorf("error parsing the hostname %w", err)
38+
}
39+
40+
//host = GitHubHost("https://" + oa.Hostname)
3541
}
3642

3743
code, err := device.RequestCode(httpClient, host.DeviceCodeURL, oa.ClientID, oa.Scopes)

Diff for: oauth_webapp.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ import (
1414
// flow, blocks until the user completes authorization and is redirected back, and returns the access token.
1515
func (oa *Flow) WebAppFlow() (*api.AccessToken, error) {
1616
host := oa.Host
17+
1718
if host == nil {
18-
host = GitHubHost("https://" + oa.Hostname)
19+
_, err := NewGitHubHost("https://" + oa.Hostname)
20+
if err != nil {
21+
return nil, fmt.Errorf("error parsing the hostname %w", err)
22+
}
23+
//host = GitHubHost("https://" + oa.Hostname)
1924
}
2025

2126
flow, err := webapp.InitFlow()

0 commit comments

Comments
 (0)