|
3 | 3 | package oauth |
4 | 4 |
|
5 | 5 | import ( |
6 | | - "errors" |
7 | | - "fmt" |
8 | | - "io" |
9 | | - "net/http" |
10 | | - "net/url" |
11 | | - "strings" |
| 6 | + "errors" |
| 7 | + "fmt" |
| 8 | + "io" |
| 9 | + "net/http" |
| 10 | + "net/url" |
| 11 | + "strings" |
12 | 12 |
|
13 | | - "github.com/cli/oauth/api" |
14 | | - "github.com/cli/oauth/device" |
| 13 | + "github.com/cli/oauth/api" |
| 14 | + "github.com/cli/oauth/device" |
15 | 15 | ) |
16 | 16 |
|
17 | 17 | type httpClient interface { |
18 | | - PostForm(string, url.Values) (*http.Response, error) |
| 18 | + PostForm(string, url.Values) (*http.Response, error) |
19 | 19 | } |
20 | 20 |
|
21 | 21 | // Host defines the endpoints used to authorize against an OAuth server. |
22 | 22 | type Host struct { |
23 | | - DeviceCodeURL string |
24 | | - AuthorizeURL string |
25 | | - TokenURL string |
| 23 | + DeviceCodeURL string |
| 24 | + AuthorizeURL string |
| 25 | + TokenURL string |
26 | 26 | } |
27 | 27 |
|
28 | 28 | func NewGitHubHost(hostURL string) (*Host, error) { |
29 | | - u, err := url.Parse(strings.TrimSpace(hostURL)) |
30 | | - if err != nil { |
31 | | - return nil, err |
32 | | - } |
| 29 | + base, err := url.Parse(strings.TrimSpace(hostURL)) |
| 30 | + if err != nil { |
| 31 | + return nil, err |
| 32 | + } |
33 | 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 |
| 34 | + createURL := func(path string) string { |
| 35 | + u := *base // Copy base URL |
| 36 | + u.Path = path |
| 37 | + return u.String() |
| 38 | + } |
| 39 | + |
| 40 | + return &Host{ |
| 41 | + DeviceCodeURL: createURL("/login/device/code"), |
| 42 | + AuthorizeURL: createURL("/login/oauth/authorize"), |
| 43 | + TokenURL: createURL("/login/oauth/access_token"), |
| 44 | + }, nil |
39 | 45 | } |
40 | 46 |
|
41 | 47 | // GitHubHost constructs a Host from the given URL to a GitHub instance. |
42 | 48 | func GitHubHost(hostURL string) *Host { |
43 | | - u, _ := url.Parse(hostURL) |
| 49 | + u, _ := url.Parse(hostURL) |
44 | 50 |
|
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 | | - } |
| 51 | + return &Host{ |
| 52 | + DeviceCodeURL: fmt.Sprintf("%s://%s/login/device/code", u.Scheme, u.Host), |
| 53 | + AuthorizeURL: fmt.Sprintf("%s://%s/login/oauth/authorize", u.Scheme, u.Host), |
| 54 | + TokenURL: fmt.Sprintf("%s://%s/login/oauth/access_token", u.Scheme, u.Host), |
| 55 | + } |
50 | 56 | } |
51 | 57 |
|
52 | 58 | // Flow facilitates a single OAuth authorization flow. |
53 | 59 | type Flow struct { |
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 |
| 60 | + // The hostname to authorize the app with. |
| 61 | + // |
| 62 | + // Deprecated: Use Host instead. |
| 63 | + Hostname string |
| 64 | + // Host configuration to authorize the app with. |
| 65 | + Host *Host |
| 66 | + // OAuth scopes to request from the user. |
| 67 | + Scopes []string |
| 68 | + // OAuth application ID. |
| 69 | + ClientID string |
| 70 | + // OAuth application secret. Only applicable in web application flow. |
| 71 | + ClientSecret string |
| 72 | + // The localhost URI for web application flow callback, e.g. "http://127.0.0.1/callback". |
| 73 | + CallbackURI string |
68 | 74 |
|
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) |
| 75 | + // Display a one-time code to the user. Receives the code and the browser URL as arguments. Defaults to printing the |
| 76 | + // code to the user on Stdout with instructions to copy the code and to press Enter to continue in their browser. |
| 77 | + DisplayCode func(string, string) error |
| 78 | + // Open a web browser at a URL. Defaults to opening the default system browser. |
| 79 | + BrowseURL func(string) error |
| 80 | + // Render an HTML page to the user upon completion of web application flow. The default is to |
| 81 | + // render a simple message that informs the user they can close the browser tab and return to the app. |
| 82 | + WriteSuccessHTML func(io.Writer) |
77 | 83 |
|
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 |
| 84 | + // The HTTP client to use for API POST requests. Defaults to http.DefaultClient. |
| 85 | + HTTPClient httpClient |
| 86 | + // The stream to listen to keyboard input on. Defaults to os.Stdin. |
| 87 | + Stdin io.Reader |
| 88 | + // The stream to print UI messages to. Defaults to os.Stdout. |
| 89 | + Stdout io.Writer |
84 | 90 | } |
85 | 91 |
|
86 | 92 | // DetectFlow tries to perform Device flow first and falls back to Web application flow. |
87 | 93 | func (oa *Flow) DetectFlow() (*api.AccessToken, error) { |
88 | | - accessToken, err := oa.DeviceFlow() |
89 | | - if errors.Is(err, device.ErrUnsupported) { |
90 | | - return oa.WebAppFlow() |
91 | | - } |
92 | | - return accessToken, err |
| 94 | + accessToken, err := oa.DeviceFlow() |
| 95 | + if errors.Is(err, device.ErrUnsupported) { |
| 96 | + return oa.WebAppFlow() |
| 97 | + } |
| 98 | + return accessToken, err |
93 | 99 | } |
0 commit comments