@@ -52,6 +52,9 @@ type OAuth2AuthenticatorOptions struct {
52
52
53
53
// The object retrieving the OIDC client configuration from the given domain
54
54
ClientsStore OIDCClientsStore
55
+
56
+ // Indicates whether the client info have to be read from spoe messages
57
+ ReadClientInfoFromMessages bool
55
58
}
56
59
57
60
// State the content of the state
@@ -72,6 +75,16 @@ type OIDCAuthenticator struct {
72
75
options OIDCAuthenticatorOptions
73
76
}
74
77
78
+ type OAuthArgs struct {
79
+ ssl bool
80
+ host string
81
+ pathq string
82
+ clientid string
83
+ clientsecret string
84
+ redirecturl string
85
+ cookie string
86
+ }
87
+
75
88
// NewOIDCAuthenticator create an instance of an OIDC authenticator
76
89
func NewOIDCAuthenticator (options OIDCAuthenticatorOptions ) * OIDCAuthenticator {
77
90
if len (options .SignatureSecret ) < 16 {
@@ -164,18 +177,20 @@ func (oa *OIDCAuthenticator) checkCookie(cookieValue string, domain string) erro
164
177
return err
165
178
}
166
179
167
- func extractOAuth2Args (msg * spoe.Message ) ( bool , string , string , string , error ) {
180
+ func extractOAuth2Args (msg * spoe.Message , readClientInfoFromMessages bool ) ( OAuthArgs , error ) {
168
181
var ssl * bool
169
182
var host , pathq * string
170
183
var cookie string
184
+ var clientid , clientsecret , redirecturl * string
171
185
172
186
for msg .Args .Next () {
173
187
arg := msg .Args .Arg
174
188
175
189
if arg .Name == "arg_ssl" {
176
190
x , ok := arg .Value .(bool )
177
191
if ! ok {
178
- return false , "" , "" , "" , fmt .Errorf ("SSL is not a bool: %v" , arg .Value )
192
+ return OAuthArgs {ssl : false , host : "" , pathq : "" , cookie : "" , clientid : "" , clientsecret : "" , redirecturl : "" },
193
+ fmt .Errorf ("SSL is not a bool: %v" , arg .Value )
179
194
}
180
195
181
196
ssl = new (bool )
@@ -186,7 +201,8 @@ func extractOAuth2Args(msg *spoe.Message) (bool, string, string, string, error)
186
201
if arg .Name == "arg_host" {
187
202
x , ok := arg .Value .(string )
188
203
if ! ok {
189
- return false , "" , "" , "" , fmt .Errorf ("host is not a string: %v" , arg .Value )
204
+ return OAuthArgs {ssl : false , host : "" , pathq : "" , cookie : "" , clientid : "" , clientsecret : "" , redirecturl : "" },
205
+ fmt .Errorf ("host is not a string: %v" , arg .Value )
190
206
}
191
207
192
208
host = new (string )
@@ -197,7 +213,8 @@ func extractOAuth2Args(msg *spoe.Message) (bool, string, string, string, error)
197
213
if arg .Name == "arg_pathq" {
198
214
x , ok := arg .Value .(string )
199
215
if ! ok {
200
- return false , "" , "" , "" , fmt .Errorf ("pathq is not a string: %v" , arg .Value )
216
+ return OAuthArgs {ssl : false , host : "" , pathq : "" , cookie : "" , clientid : "" , clientsecret : "" , redirecturl : "" },
217
+ fmt .Errorf ("pathq is not a string: %v" , arg .Value )
201
218
}
202
219
203
220
pathq = new (string )
@@ -214,20 +231,78 @@ func extractOAuth2Args(msg *spoe.Message) (bool, string, string, string, error)
214
231
cookie = x
215
232
continue
216
233
}
234
+
235
+ if arg .Name == "arg_client_id" {
236
+ if ! readClientInfoFromMessages {
237
+ continue
238
+ }
239
+ x , ok := arg .Value .(string )
240
+ if ! ok {
241
+ logrus .Debugf ("clientid is not defined or not a string: %v" , arg .Value )
242
+ continue
243
+ }
244
+
245
+ clientid = new (string )
246
+ * clientid = x
247
+ continue
248
+ }
249
+
250
+ if arg .Name == "arg_client_secret" {
251
+ if ! readClientInfoFromMessages {
252
+ continue
253
+ }
254
+ x , ok := arg .Value .(string )
255
+ if ! ok {
256
+ logrus .Debugf ("clientsecret is not defined or not a string: %v" , arg .Value )
257
+ continue
258
+ }
259
+
260
+ clientsecret = new (string )
261
+ * clientsecret = x
262
+ continue
263
+ }
264
+
265
+ if arg .Name == "arg_redirect_url" {
266
+ if ! readClientInfoFromMessages {
267
+ continue
268
+ }
269
+ x , ok := arg .Value .(string )
270
+ if ! ok {
271
+ logrus .Debugf ("redirecturl is not defined or not a string: %v" , arg .Value )
272
+ continue
273
+ }
274
+
275
+ redirecturl = new (string )
276
+ * redirecturl = x
277
+ continue
278
+ }
217
279
}
218
280
219
281
if ssl == nil {
220
- return false , "" , "" , "" , ErrSSLArgNotFound
282
+ return OAuthArgs {ssl : false , host : "" , pathq : "" , cookie : "" , clientid : "" , clientsecret : "" , redirecturl : "" },
283
+ ErrSSLArgNotFound
221
284
}
222
285
223
286
if host == nil {
224
- return false , "" , "" , "" , ErrHostArgNotFound
287
+ return OAuthArgs {ssl : false , host : "" , pathq : "" , cookie : "" , clientid : "" , clientsecret : "" , redirecturl : "" },
288
+ ErrHostArgNotFound
225
289
}
226
290
227
291
if pathq == nil {
228
- return false , "" , "" , "" , ErrPathqArgNotFound
292
+ return OAuthArgs {ssl : false , host : "" , pathq : "" , cookie : "" , clientid : "" , clientsecret : "" , redirecturl : "" },
293
+ ErrPathqArgNotFound
229
294
}
230
- return * ssl , * host , * pathq , cookie , nil
295
+
296
+ if clientid == nil || clientsecret == nil || redirecturl == nil {
297
+ temp := ""
298
+ clientid = & temp
299
+ clientsecret = & temp
300
+ redirecturl = & temp
301
+ }
302
+ return OAuthArgs {ssl : * ssl , host : * host , pathq : * pathq ,
303
+ cookie : cookie , clientid : * clientid ,
304
+ clientsecret : * clientsecret , redirecturl : * redirecturl },
305
+ nil
231
306
}
232
307
233
308
func (oa * OIDCAuthenticator ) computeStateSignature (state * State ) string {
@@ -252,12 +327,17 @@ func extractDomainFromHost(host string) string {
252
327
253
328
// Authenticate treat an authentication request coming from HAProxy
254
329
func (oa * OIDCAuthenticator ) Authenticate (msg * spoe.Message ) (bool , []spoe.Action , error ) {
255
- ssl , host , pathq , cookieValue , err := extractOAuth2Args (msg )
330
+ // ssl, host, pathq, clientid, clientsecret, redirecturl, cookieValue, err := extractOAuth2Args(msg, oa.options.ReadClientInfoFromMessages)
331
+ oauthArgs , err := extractOAuth2Args (msg , oa .options .ReadClientInfoFromMessages )
256
332
if err != nil {
257
333
return false , nil , fmt .Errorf ("unable to extract origin URL: %v" , err )
258
334
}
259
335
260
- domain := extractDomainFromHost (host )
336
+ domain := extractDomainFromHost (oauthArgs .host )
337
+
338
+ if oauthArgs .clientid != "" {
339
+ oa .options .ClientsStore .AddClient (domain , oauthArgs .clientid , oauthArgs .clientsecret , oauthArgs .redirecturl )
340
+ }
261
341
262
342
_ , err = oa .options .ClientsStore .GetClient (domain )
263
343
if err == ErrOIDCClientConfigNotFound {
@@ -267,8 +347,8 @@ func (oa *OIDCAuthenticator) Authenticate(msg *spoe.Message) (bool, []spoe.Actio
267
347
}
268
348
269
349
// Verify the cookie to make sure the user is authenticated
270
- if cookieValue != "" {
271
- err := oa .checkCookie (cookieValue , extractDomainFromHost (host ))
350
+ if oauthArgs . cookie != "" {
351
+ err := oa .checkCookie (oauthArgs . cookie , extractDomainFromHost (oauthArgs . host ))
272
352
if err != nil {
273
353
return false , nil , err
274
354
} else {
@@ -280,8 +360,8 @@ func (oa *OIDCAuthenticator) Authenticate(msg *spoe.Message) (bool, []spoe.Actio
280
360
281
361
var state State
282
362
state .Timestamp = currentTime
283
- state .PathAndQueryString = pathq
284
- state .SSL = ssl
363
+ state .PathAndQueryString = oauthArgs . pathq
364
+ state .SSL = oauthArgs . ssl
285
365
state .Signature = oa .computeStateSignature (& state )
286
366
287
367
stateBytes , err := msgpack .Marshal (state )
0 commit comments