Skip to content

Commit 8a55026

Browse files
committed
feat: Add support for audience in authorization request
1 parent adf5f73 commit 8a55026

7 files changed

+87
-5
lines changed

Diff for: device/device_flow.go

+20-3
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,29 @@ type CodeResponse struct {
5454
Interval int
5555
}
5656

57+
// Function signature for setting additional form values.
58+
type AuthRequestFn func(*url.Values)
59+
60+
func WithAudience(audience string) AuthRequestFn {
61+
return func(values *url.Values) {
62+
if audience != "" {
63+
values.Add("audience", audience)
64+
}
65+
}
66+
}
67+
5768
// RequestCode initiates the authorization flow by requesting a code from uri.
58-
func RequestCode(c httpClient, uri string, clientID string, scopes []string) (*CodeResponse, error) {
59-
resp, err := api.PostForm(c, uri, url.Values{
69+
func RequestCode(c httpClient, uri string, clientID string, scopes []string, extra ...AuthRequestFn) (*CodeResponse, error) {
70+
values := url.Values{
6071
"client_id": {clientID},
6172
"scope": {strings.Join(scopes, " ")},
62-
})
73+
}
74+
75+
for _, fn := range extra {
76+
fn(&values)
77+
}
78+
79+
resp, err := api.PostForm(c, uri, values)
6380
if err != nil {
6481
return nil, err
6582
}

Diff for: device/device_flow_test.go

+39-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func TestRequestCode(t *testing.T) {
5151
url string
5252
clientID string
5353
scopes []string
54+
audience string
5455
}
5556
tests := []struct {
5657
name string
@@ -126,6 +127,42 @@ func TestRequestCode(t *testing.T) {
126127
},
127128
},
128129
},
130+
{
131+
name: "with audience",
132+
args: args{
133+
http: apiClient{
134+
stubs: []apiStub{
135+
{
136+
body: "verification_uri=http://verify.me&interval=5&expires_in=99&device_code=DEVIC&user_code=123-abc&verification_uri_complete=http://verify.me/?code=123-abc",
137+
status: 200,
138+
contentType: "application/x-www-form-urlencoded; charset=utf-8",
139+
},
140+
},
141+
},
142+
url: "https://github.com/oauth",
143+
clientID: "CLIENT-ID",
144+
scopes: []string{"repo", "gist"},
145+
audience: "https://api.github.com",
146+
},
147+
want: &CodeResponse{
148+
DeviceCode: "DEVIC",
149+
UserCode: "123-abc",
150+
VerificationURI: "http://verify.me",
151+
VerificationURIComplete: "http://verify.me/?code=123-abc",
152+
ExpiresIn: 99,
153+
Interval: 5,
154+
},
155+
posts: []postArgs{
156+
{
157+
url: "https://github.com/oauth",
158+
params: url.Values{
159+
"client_id": {"CLIENT-ID"},
160+
"scope": {"repo gist"},
161+
"audience": {"https://api.github.com"},
162+
},
163+
},
164+
},
165+
},
129166
{
130167
name: "unsupported",
131168
args: args{
@@ -237,7 +274,8 @@ func TestRequestCode(t *testing.T) {
237274
}
238275
for _, tt := range tests {
239276
t.Run(tt.name, func(t *testing.T) {
240-
got, err := RequestCode(&tt.args.http, tt.args.url, tt.args.clientID, tt.args.scopes)
277+
got, err := RequestCode(&tt.args.http, tt.args.url,
278+
tt.args.clientID, tt.args.scopes, WithAudience(tt.args.audience))
241279
if (err != nil) != (tt.wantErr != "") {
242280
t.Errorf("RequestCode() error = %v, wantErr %v", err, tt.wantErr)
243281
return

Diff for: oauth.go

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ type Flow struct {
4545
Host *Host
4646
// OAuth scopes to request from the user.
4747
Scopes []string
48+
// OAuth audience to request from the user.
49+
Audience string
4850
// OAuth application ID.
4951
ClientID string
5052
// OAuth application secret. Only applicable in web application flow.

Diff for: oauth_device.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ func (oa *Flow) DeviceFlow() (*api.AccessToken, error) {
3434
host = GitHubHost("https://" + oa.Hostname)
3535
}
3636

37-
code, err := device.RequestCode(httpClient, host.DeviceCodeURL, oa.ClientID, oa.Scopes)
37+
code, err := device.RequestCode(httpClient, host.DeviceCodeURL,
38+
oa.ClientID, oa.Scopes, device.WithAudience(oa.Audience))
3839
if err != nil {
3940
return nil, err
4041
}

Diff for: oauth_webapp.go

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func (oa *Flow) WebAppFlow() (*api.AccessToken, error) {
2727
ClientID: oa.ClientID,
2828
RedirectURI: oa.CallbackURI,
2929
Scopes: oa.Scopes,
30+
Audience: oa.Audience,
3031
AllowSignup: true,
3132
}
3233
browserURL, err := flow.BrowserURL(host.AuthorizeURL, params)

Diff for: webapp/webapp_flow.go

+5
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type BrowserParams struct {
4747
ClientID string
4848
RedirectURI string
4949
Scopes []string
50+
Audience string
5051
LoginHandle string
5152
AllowSignup bool
5253
}
@@ -68,6 +69,10 @@ func (flow *Flow) BrowserURL(baseURL string, params BrowserParams) (string, erro
6869
q.Set("redirect_uri", ru.String())
6970
q.Set("scope", strings.Join(params.Scopes, " "))
7071
q.Set("state", flow.state)
72+
73+
if params.Audience != "" {
74+
q.Set("audience", params.Audience)
75+
}
7176
if params.LoginHandle != "" {
7277
q.Set("login", params.LoginHandle)
7378
}

Diff for: webapp/webapp_flow_test.go

+18
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,24 @@ func TestFlow_BrowserURL(t *testing.T) {
5151
want: "https://github.com/authorize?client_id=CLIENT-ID&redirect_uri=http%3A%2F%2F127.0.0.1%3A12345%2Fhello&scope=repo+read%3Aorg&state=xy%2Fz",
5252
wantErr: false,
5353
},
54+
{
55+
name: "happy path with audience",
56+
fields: fields{
57+
server: server,
58+
state: "xy/z",
59+
},
60+
args: args{
61+
baseURL: "https://github.com/authorize",
62+
params: BrowserParams{
63+
ClientID: "CLIENT-ID",
64+
RedirectURI: "http://127.0.0.1/hello",
65+
Scopes: []string{"repo", "read:org"},
66+
AllowSignup: true,
67+
Audience: "https://api.github.com",
68+
},
69+
},
70+
want: "https://github.com/authorize?audience=https%3A%2F%2Fapi.github.com&client_id=CLIENT-ID&redirect_uri=http%3A%2F%2F127.0.0.1%3A12345%2Fhello&scope=repo+read%3Aorg&state=xy%2Fz",
71+
},
5472
}
5573
for _, tt := range tests {
5674
t.Run(tt.name, func(t *testing.T) {

0 commit comments

Comments
 (0)