1+ package clientcredentials
2+
3+ import (
4+ "encoding/base64"
5+ "fmt"
6+ "net/http"
7+ "net/http/httptest"
8+ "net/url"
9+ "strings"
10+ "testing"
11+ )
12+
13+ func TestHandleTokenRequest (t * testing.T ) {
14+ tests := []struct {
15+ name string
16+ setupRequest func () * http.Request
17+ wantStatus int
18+ wantAccessToken string
19+ }{
20+ {
21+ name : "valid form credentials" ,
22+ setupRequest : func () * http.Request {
23+ form := url.Values {}
24+ form .Set ("grant_type" , "client_credentials" )
25+ form .Set ("client_id" , "speakeasy-sdks" )
26+ form .Set ("client_secret" , "supersecret-123" )
27+ form .Set ("scope" , "read write" )
28+
29+ req := httptest .NewRequest (http .MethodPost , "/token" , strings .NewReader (form .Encode ()))
30+ req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
31+ return req
32+ },
33+ wantStatus : http .StatusOK ,
34+ wantAccessToken : firstAccessToken ,
35+ },
36+ {
37+ name : "valid basic auth" ,
38+ setupRequest : func () * http.Request {
39+ form := url.Values {}
40+ form .Set ("grant_type" , "client_credentials" )
41+ form .Set ("scope" , "read write" )
42+
43+ req := httptest .NewRequest (http .MethodPost , "/token" , strings .NewReader (form .Encode ()))
44+ req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
45+
46+ // Create basic auth header
47+ creds := base64 .StdEncoding .EncodeToString ([]byte ("speakeasy-sdks:supersecret-123" ))
48+ req .Header .Set ("Authorization" , fmt .Sprintf ("Basic %s" , creds ))
49+
50+ return req
51+ },
52+ wantStatus : http .StatusOK ,
53+ wantAccessToken : firstAccessToken ,
54+ },
55+ {
56+ name : "invalid basic auth format" ,
57+ setupRequest : func () * http.Request {
58+ req := httptest .NewRequest (http .MethodPost , "/token" , nil )
59+ req .Header .Set ("Authorization" , "Basic invalid-base64" )
60+ return req
61+ },
62+ wantStatus : http .StatusUnauthorized ,
63+ },
64+ {
65+ name : "missing credentials in basic auth" ,
66+ setupRequest : func () * http.Request {
67+ req := httptest .NewRequest (http .MethodPost , "/token" , nil )
68+ // Encode just username without password
69+ creds := base64 .StdEncoding .EncodeToString ([]byte ("speakeasy-sdks" ))
70+ req .Header .Set ("Authorization" , fmt .Sprintf ("Basic %s" , creds ))
71+ return req
72+ },
73+ wantStatus : http .StatusUnauthorized ,
74+ },
75+ {
76+ name : "invalid credentials in basic auth" ,
77+ setupRequest : func () * http.Request {
78+ form := url.Values {}
79+ form .Set ("grant_type" , "client_credentials" )
80+ req := httptest .NewRequest (http .MethodPost , "/token" , strings .NewReader (form .Encode ()))
81+ req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
82+ creds := base64 .StdEncoding .EncodeToString ([]byte ("wrong:wrong" ))
83+ req .Header .Set ("Authorization" , fmt .Sprintf ("Basic %s" , creds ))
84+
85+ return req
86+ },
87+ wantStatus : http .StatusUnauthorized ,
88+ },
89+ {
90+ name : "missing required scope in basic auth" ,
91+ setupRequest : func () * http.Request {
92+ form := url.Values {}
93+ form .Set ("grant_type" , "client_credentials" )
94+ form .Set ("scope" , "read" ) // missing write scope
95+
96+ req := httptest .NewRequest (http .MethodPost , "/token" , strings .NewReader (form .Encode ()))
97+ req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
98+
99+ creds := base64 .StdEncoding .EncodeToString ([]byte ("speakeasy-sdks:supersecret-123" ))
100+ req .Header .Set ("Authorization" , fmt .Sprintf ("Basic %s" , creds ))
101+
102+ return req
103+ },
104+ wantStatus : http .StatusBadRequest ,
105+ },
106+ {
107+ name : "case insensitive basic prefix" ,
108+ setupRequest : func () * http.Request {
109+ form := url.Values {}
110+ form .Set ("grant_type" , "client_credentials" )
111+ form .Set ("scope" , "read write" )
112+
113+ req := httptest .NewRequest (http .MethodPost , "/token" , strings .NewReader (form .Encode ()))
114+ req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
115+
116+ creds := base64 .StdEncoding .EncodeToString ([]byte ("speakeasy-sdks:supersecret-123" ))
117+ req .Header .Set ("Authorization" , fmt .Sprintf ("BASIC %s" , creds ))
118+
119+ return req
120+ },
121+ wantStatus : http .StatusOK ,
122+ wantAccessToken : firstAccessToken ,
123+ },
124+ }
125+
126+ for _ , tt := range tests {
127+ t .Run (tt .name , func (t * testing.T ) {
128+ w := httptest .NewRecorder ()
129+ HandleTokenRequest (w , tt .setupRequest ())
130+
131+ if got := w .Code ; got != tt .wantStatus {
132+ t .Errorf ("HandleTokenRequest() status = %v, want %v" , got , tt .wantStatus )
133+ }
134+
135+ if tt .wantStatus == http .StatusOK {
136+ if ! strings .Contains (w .Body .String (), tt .wantAccessToken ) {
137+ t .Errorf ("HandleTokenRequest() response doesn't contain expected access token" )
138+ }
139+ }
140+ })
141+ }
142+ }
0 commit comments