@@ -3,13 +3,12 @@ package coderd_test
3
3
import (
4
4
"context"
5
5
"crypto"
6
- "crypto/rand"
7
- "crypto/rsa"
6
+ "fmt"
8
7
"io"
9
8
"net/http"
10
9
"net/url"
10
+ "strings"
11
11
"testing"
12
- "time"
13
12
14
13
"github.com/coreos/go-oidc/v3/oidc"
15
14
"github.com/golang-jwt/jwt"
@@ -450,17 +449,19 @@ func TestUserOIDC(t *testing.T) {
450
449
tc := tc
451
450
t .Run (tc .Name , func (t * testing.T ) {
452
451
t .Parallel ()
453
- config := createOIDCConfig (t , tc .Claims )
452
+ conf := coderdtest .NewOIDCConfig (t , "" )
453
+
454
+ config := conf .OIDCConfig ()
454
455
config .AllowSignups = tc .AllowSignups
455
456
config .EmailDomain = tc .EmailDomain
457
+
456
458
client := coderdtest .New (t , & coderdtest.Options {
457
459
OIDCConfig : config ,
458
460
})
459
- resp := oidcCallback (t , client )
461
+ resp := oidcCallback (t , client , conf . EncodeClaims ( t , tc . Claims ) )
460
462
assert .Equal (t , tc .StatusCode , resp .StatusCode )
461
463
462
- ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
463
- defer cancel ()
464
+ ctx , _ := testutil .Context (t )
464
465
465
466
if tc .Username != "" {
466
467
client .SessionToken = authCookieValue (resp .Cookies ())
@@ -478,10 +479,50 @@ func TestUserOIDC(t *testing.T) {
478
479
})
479
480
}
480
481
482
+ t .Run ("AlternateUsername" , func (t * testing.T ) {
483
+ t .Parallel ()
484
+
485
+ conf := coderdtest .NewOIDCConfig (t , "" )
486
+
487
+ config := conf .OIDCConfig ()
488
+ config .AllowSignups = true
489
+
490
+ client := coderdtest .New (t , & coderdtest.Options {
491
+ OIDCConfig : config ,
492
+ })
493
+
494
+ code := conf .EncodeClaims (t , jwt.MapClaims {
495
+
496
+ })
497
+ resp := oidcCallback (t , client , code )
498
+ assert .Equal (t , http .StatusTemporaryRedirect , resp .StatusCode )
499
+
500
+ ctx , _ := testutil .Context (t )
501
+
502
+ client .SessionToken = authCookieValue (resp .Cookies ())
503
+ user , err := client .User (ctx , "me" )
504
+ require .NoError (t , err )
505
+ require .Equal (t , "jon" , user .Username )
506
+
507
+ // Pass a different subject field so that we prompt creating a
508
+ // new user.
509
+ code = conf .EncodeClaims (t , jwt.MapClaims {
510
+
511
+ "sub" : "diff" ,
512
+ })
513
+ resp = oidcCallback (t , client , code )
514
+ assert .Equal (t , http .StatusTemporaryRedirect , resp .StatusCode )
515
+
516
+ client .SessionToken = authCookieValue (resp .Cookies ())
517
+ user , err = client .User (ctx , "me" )
518
+ require .NoError (t , err )
519
+ require .True (t , strings .HasPrefix (user .Username , "jon-" ), "username %q should have prefix %q" , user .Username , "jon-" )
520
+ })
521
+
481
522
t .Run ("Disabled" , func (t * testing.T ) {
482
523
t .Parallel ()
483
524
client := coderdtest .New (t , nil )
484
- resp := oidcCallback (t , client )
525
+ resp := oidcCallback (t , client , "asdf" )
485
526
require .Equal (t , http .StatusPreconditionRequired , resp .StatusCode )
486
527
})
487
528
@@ -492,7 +533,7 @@ func TestUserOIDC(t *testing.T) {
492
533
OAuth2Config : & oauth2Config {},
493
534
},
494
535
})
495
- resp := oidcCallback (t , client )
536
+ resp := oidcCallback (t , client , "asdf" )
496
537
require .Equal (t , http .StatusBadRequest , resp .StatusCode )
497
538
})
498
539
@@ -514,48 +555,16 @@ func TestUserOIDC(t *testing.T) {
514
555
Verifier : verifier ,
515
556
},
516
557
})
517
- resp := oidcCallback (t , client )
558
+ resp := oidcCallback (t , client , "asdf" )
518
559
require .Equal (t , http .StatusBadRequest , resp .StatusCode )
519
560
})
520
561
}
521
562
522
- // createOIDCConfig generates a new OIDCConfig that returns a static token
523
- // with the claims provided.
524
- func createOIDCConfig (t * testing.T , claims jwt.MapClaims ) * coderd.OIDCConfig {
525
- t .Helper ()
526
- key , err := rsa .GenerateKey (rand .Reader , 2048 )
527
- require .NoError (t , err )
528
-
529
- // https://datatracker.ietf.org/doc/html/rfc7519#section-4.1
530
- claims ["exp" ] = time .Now ().Add (time .Hour ).UnixMilli ()
531
- claims ["iss" ] = "https://coder.com"
532
- claims ["sub" ] = "hello"
533
-
534
- signed , err := jwt .NewWithClaims (jwt .SigningMethodRS256 , claims ).SignedString (key )
535
- require .NoError (t , err )
536
-
537
- verifier := oidc .NewVerifier ("https://coder.com" , & oidc.StaticKeySet {
538
- PublicKeys : []crypto.PublicKey {key .Public ()},
539
- }, & oidc.Config {
540
- SkipClientIDCheck : true ,
541
- })
542
-
543
- return & coderd.OIDCConfig {
544
- OAuth2Config : & oauth2Config {
545
- token : (& oauth2.Token {
546
- AccessToken : "token" ,
547
- }).WithExtra (map [string ]interface {}{
548
- "id_token" : signed ,
549
- }),
550
- },
551
- Verifier : verifier ,
552
- }
553
- }
554
-
555
563
func oauth2Callback (t * testing.T , client * codersdk.Client ) * http.Response {
556
564
client .HTTPClient .CheckRedirect = func (req * http.Request , via []* http.Request ) error {
557
565
return http .ErrUseLastResponse
558
566
}
567
+
559
568
state := "somestate"
560
569
oauthURL , err := client .URL .Parse ("/api/v2/users/oauth2/github/callback?code=asd&state=" + state )
561
570
require .NoError (t , err )
@@ -573,19 +582,18 @@ func oauth2Callback(t *testing.T, client *codersdk.Client) *http.Response {
573
582
return res
574
583
}
575
584
576
- func oidcCallback (t * testing.T , client * codersdk.Client ) * http.Response {
585
+ func oidcCallback (t * testing.T , client * codersdk.Client , code string ) * http.Response {
577
586
t .Helper ()
578
587
client .HTTPClient .CheckRedirect = func (req * http.Request , via []* http.Request ) error {
579
588
return http .ErrUseLastResponse
580
589
}
581
- state := "somestate"
582
- oauthURL , err := client .URL .Parse ("/api/v2/users/oidc/callback?code=asd&state=" + state )
590
+ oauthURL , err := client .URL .Parse (fmt .Sprintf ("/api/v2/users/oidc/callback?code=%s&state=somestate" , code ))
583
591
require .NoError (t , err )
584
592
req , err := http .NewRequestWithContext (context .Background (), "GET" , oauthURL .String (), nil )
585
593
require .NoError (t , err )
586
594
req .AddCookie (& http.Cookie {
587
595
Name : codersdk .OAuth2StateKey ,
588
- Value : state ,
596
+ Value : "somestate" ,
589
597
})
590
598
res , err := client .HTTPClient .Do (req )
591
599
require .NoError (t , err )
0 commit comments