@@ -3,13 +3,80 @@ package u2m
33import (
44 "context"
55 "fmt"
6+ "html/template"
67 "net/http"
8+ "net/http/httptest"
9+ "net/url"
710 "testing"
811
912 "github.com/databricks/databricks-sdk-go/httpclient/fixtures"
1013 "golang.org/x/oauth2"
1114)
1215
16+ func TestCallbackServer_HandlerWithIssuerBindsIssuerToResult (t * testing.T ) {
17+ browserOpened := make (chan string , 1 )
18+ cb := & callbackServer {
19+ ctx : context .Background (),
20+ browser : func (redirect string ) error {
21+ browserOpened <- redirect
22+ return nil
23+ },
24+ renderErrCh : make (chan error ),
25+ feedbackCh : make (chan oauthResult , 2 ),
26+ tmpl : template .Must (template .New ("page" ).Parse ("" )),
27+ }
28+
29+ const authCodeURL = "https://login.databricks.com/?destination_url=%2Foidc%2Fv1%2Fauthorize"
30+ legitimate := struct {
31+ code string
32+ state string
33+ issuer string
34+ }{
35+ code : "legit-code" ,
36+ state : "legit-state" ,
37+ issuer : "https://adb-123.azuredatabricks.net/oidc" ,
38+ }
39+
40+ serveCallback := func (code , state , issuer string ) {
41+ callbackURL := fmt .Sprintf ("/?code=%s&state=%s&iss=%s" ,
42+ url .QueryEscape (code ), url .QueryEscape (state ), url .QueryEscape (issuer ))
43+ req := httptest .NewRequest (http .MethodGet , callbackURL , nil )
44+ rec := httptest .NewRecorder ()
45+ cb .ServeHTTP (rec , req )
46+ if rec .Code != http .StatusOK {
47+ t .Fatalf ("ServeHTTP status = %d, want %d" , rec .Code , http .StatusOK )
48+ }
49+ }
50+
51+ // Queue two callbacks with different code/state/iss; the handler must
52+ // return the values from the first result and not interleave.
53+ serveCallback (legitimate .code , legitimate .state , legitimate .issuer )
54+ serveCallback ("second-code" , "second-state" , "https://other.example/oidc" )
55+
56+ code , state , issuer , err := cb .handlerWithIssuer (authCodeURL )
57+ if err != nil {
58+ t .Fatalf ("handlerWithIssuer(): %v" , err )
59+ }
60+ if code != legitimate .code {
61+ t .Errorf ("code = %q, want %q" , code , legitimate .code )
62+ }
63+ if state != legitimate .state {
64+ t .Errorf ("state = %q, want %q" , state , legitimate .state )
65+ }
66+ if issuer != legitimate .issuer {
67+ t .Errorf ("issuer = %q, want %q" , issuer , legitimate .issuer )
68+ }
69+
70+ select {
71+ case got := <- browserOpened :
72+ if got != authCodeURL {
73+ t .Errorf ("browser opened %q, want %q" , got , authCodeURL )
74+ }
75+ default :
76+ t .Fatal ("browser was not opened" )
77+ }
78+ }
79+
1380func TestCallbackServer_ExtractsIssuer (t * testing.T ) {
1481 ctx := context .Background ()
1582
@@ -64,11 +131,6 @@ func TestCallbackServer_ExtractsIssuer(t *testing.T) {
64131 }
65132 defer cb .Close ()
66133
67- // Verify issuer is empty before any callback.
68- if got := cb .Issuer (); got != "" {
69- t .Fatalf ("Issuer() before callback: want %q, got %q" , "" , got )
70- }
71-
72134 // Fire a callback with iss parameter.
73135 issuerURL := "https://adb-123.azuredatabricks.net/oidc"
74136 resp , err := http .Get (fmt .Sprintf ("http://%s?code=xxx&state=yyy&iss=%s" , p .redirectAddr , issuerURL ))
@@ -77,11 +139,9 @@ func TestCallbackServer_ExtractsIssuer(t *testing.T) {
77139 }
78140 defer resp .Body .Close ()
79141
80- // Drain the feedback channel so ServeHTTP completes.
81- <- cb .feedbackCh
82-
83- if got := cb .Issuer (); got != issuerURL {
84- t .Fatalf ("Issuer(): want %q, got %q" , issuerURL , got )
142+ res := <- cb .feedbackCh
143+ if got := res .Issuer ; got != issuerURL {
144+ t .Fatalf ("result Issuer: want %q, got %q" , issuerURL , got )
85145 }
86146}
87147
@@ -128,11 +188,9 @@ func TestCallbackServer_NoIssuer(t *testing.T) {
128188 }
129189 defer resp .Body .Close ()
130190
131- // Drain the feedback channel so ServeHTTP completes.
132- <- cb .feedbackCh
133-
134- if got := cb .Issuer (); got != "" {
135- t .Fatalf ("Issuer(): want %q, got %q" , "" , got )
191+ res := <- cb .feedbackCh
192+ if got := res .Issuer ; got != "" {
193+ t .Fatalf ("result Issuer: want %q, got %q" , "" , got )
136194 }
137195}
138196
@@ -180,10 +238,8 @@ func TestCallbackServer_IssuerWithAccountPath(t *testing.T) {
180238 }
181239 defer resp .Body .Close ()
182240
183- // Drain the feedback channel so ServeHTTP completes.
184- <- cb .feedbackCh
185-
186- if got := cb .Issuer (); got != issuerURL {
187- t .Fatalf ("Issuer(): want %q, got %q" , issuerURL , got )
241+ res := <- cb .feedbackCh
242+ if got := res .Issuer ; got != issuerURL {
243+ t .Fatalf ("result Issuer: want %q, got %q" , issuerURL , got )
188244 }
189245}
0 commit comments