1
1
package main
2
2
3
3
import (
4
+ "encoding/json"
4
5
"flag"
5
6
"log"
6
7
"os"
@@ -9,15 +10,21 @@ import (
9
10
"time"
10
11
11
12
"github.com/golang-jwt/jwt/v4"
13
+ "github.com/stretchr/testify/require"
12
14
15
+ "cdr.dev/slog"
16
+ "cdr.dev/slog/sloggers/sloghuman"
13
17
"github.com/coder/coder/v2/coderd/coderdtest/oidctest"
18
+ "github.com/coder/coder/v2/codersdk"
14
19
)
15
20
16
21
// Flags
17
22
var (
18
23
expiry = flag .Duration ("expiry" ,time .Minute * 5 ,"Token expiry" )
19
24
clientID = flag .String ("client-id" ,"static-client-id" ,"Client ID, set empty to be random" )
20
25
clientSecret = flag .String ("client-sec" ,"static-client-secret" ,"Client Secret, set empty to be random" )
26
+ // By default, no regex means it will never match anything. So at least default to matching something.
27
+ extRegex = flag .String ("ext-regex" ,`^(https?://)?example\.com(/.*)?$` ,"External auth regex" )
21
28
)
22
29
23
30
func main () {
@@ -37,6 +44,12 @@ func main() {
37
44
},nil ,nil )
38
45
}
39
46
47
+ type withClientSecret struct {
48
+ // We never unmarshal this in prod, but we need this field for testing.
49
+ ClientSecret string `json:"client_secret"`
50
+ codersdk.ExternalAuthConfig
51
+ }
52
+
40
53
// RunIDP needs the testing.T because our oidctest package requires the
41
54
// testing.T.
42
55
func RunIDP ()func (t * testing.T ) {
@@ -48,15 +61,44 @@ func RunIDP() func(t *testing.T) {
48
61
oidctest .WithDefaultExpire (* expiry ),
49
62
oidctest .WithStaticCredentials (* clientID ,* clientSecret ),
50
63
oidctest .WithIssuer ("http://localhost:4500" ),
64
+ oidctest .WithLogger (slog .Make (sloghuman .Sink (os .Stderr ))),
51
65
)
52
66
id ,sec := idp .AppCredentials ()
53
67
prov := idp .WellknownConfig ()
68
+ const appID = "fake"
69
+ coderCfg := idp .ExternalAuthConfig (t ,appID ,nil )
54
70
55
71
log .Println ("IDP Issuer URL" ,idp .IssuerURL ())
56
72
log .Println ("Coderd Flags" )
57
- log .Printf (`--external-auth-providers='[{"type":"fake","client_id":"%s","client_secret":"%s","auth_url":"%s","token_url":"%s","validate_url":"%s","scopes":["openid","email","profile"]}]'` ,
58
- id ,sec ,prov .AuthURL ,prov .TokenURL ,prov .UserInfoURL ,
59
- )
73
+ deviceCodeURL := ""
74
+ if coderCfg .DeviceAuth != nil {
75
+ deviceCodeURL = coderCfg .DeviceAuth .CodeURL
76
+ }
77
+ cfg := withClientSecret {
78
+ ClientSecret :sec ,
79
+ ExternalAuthConfig : codersdk.ExternalAuthConfig {
80
+ Type :appID ,
81
+ ClientID :id ,
82
+ ClientSecret :sec ,
83
+ ID :appID ,
84
+ AuthURL :prov .AuthURL ,
85
+ TokenURL :prov .TokenURL ,
86
+ ValidateURL :prov .ExternalAuthURL ,
87
+ AppInstallURL :coderCfg .AppInstallURL ,
88
+ AppInstallationsURL :coderCfg .AppInstallationsURL ,
89
+ NoRefresh :false ,
90
+ Scopes : []string {"openid" ,"email" ,"profile" },
91
+ ExtraTokenKeys :coderCfg .ExtraTokenKeys ,
92
+ DeviceFlow :coderCfg .DeviceAuth != nil ,
93
+ DeviceCodeURL :deviceCodeURL ,
94
+ Regex :* extRegex ,
95
+ DisplayName :coderCfg .DisplayName ,
96
+ DisplayIcon :coderCfg .DisplayIcon ,
97
+ },
98
+ }
99
+ data ,err := json .Marshal ([]withClientSecret {cfg })
100
+ require .NoError (t ,err )
101
+ log .Printf (`--external-auth-providers='%s'` ,string (data ))
60
102
61
103
log .Println ("Press Ctrl+C to exit" )
62
104
c := make (chan os.Signal ,1 )