@@ -112,7 +112,7 @@ func (g *Goic) AddProvider(p *Provider) *Provider {
112
112
}
113
113
114
114
if _ , err := p .getWellKnown (); err != nil {
115
- log . Fatalf ( "goic provider %s: cannot load well-known configuration: %s" , p . Name , err . Error () )
115
+ p . SetErr ( err )
116
116
}
117
117
118
118
g .providers [p .Name ] = p
@@ -150,21 +150,30 @@ func (g *Goic) RequestAuth(p *Provider, state, nonce, redir string, res http.Res
150
150
// AuthRedirectURL gives the full auth redirect URL for the provider
151
151
// It returns empty string when there is an error
152
152
func AuthRedirectURL (p * Provider , state , nonce , redir string ) string {
153
- redirect , err := http .NewRequest ("GET" , p .wellKnown . AuthURI , nil )
153
+ redirect , err := http .NewRequest ("GET" , p .GetURI ( "auth" ) , nil )
154
154
if err != nil {
155
155
return ""
156
156
}
157
157
158
158
qry := redirect .URL .Query ()
159
159
qry .Add ("response_type" , "code" )
160
+ if p .ResType != "" {
161
+ qry .Set ("response_type" , p .ResType )
162
+ }
163
+
160
164
qry .Add ("redirect_uri" , redir )
161
165
qry .Add ("client_id" , p .clientID )
162
166
qry .Add ("scope" , p .Scope )
163
167
qry .Add ("state" , state )
164
168
qry .Add ("nonce" , nonce )
165
169
redirect .URL .RawQuery = qry .Encode ()
166
170
167
- return redirect .URL .String ()
171
+ query := ""
172
+ if p .QueryFn != nil {
173
+ query = "&" + p .QueryFn ()
174
+ }
175
+
176
+ return redirect .URL .String () + query
168
177
}
169
178
170
179
// checkState checks if given state is valid (i.e. known)
@@ -187,26 +196,33 @@ func (g *Goic) checkState(state string) (string, error) {
187
196
188
197
// Authenticate tries to authenticate a user by given code and nonce
189
198
// It is where token is requested and validated
190
- func (g * Goic ) Authenticate (p * Provider , code , nonce , redir string ) (* Token , error ) {
199
+ func (g * Goic ) Authenticate (p * Provider , codeOrTok , nonce , redir string ) (tok * Token , err error ) {
200
+ tok = & Token {Provider : p .Name }
191
201
if ! g .Supports (p .Name ) {
192
- return & Token { Provider : p . Name } , ErrProviderSupport
202
+ return tok , ErrProviderSupport
193
203
}
194
204
195
- tok , err := g .getToken (p , code , redir , "authorization_code" )
196
- if err != nil {
197
- return tok , err
205
+ isCode := p .ResType == "" || strings .Contains (" " + p .ResType + " " , " code " )
206
+ // get token from code or just parse token
207
+ if isCode {
208
+ tok , err = g .getToken (p , codeOrTok , redir , "authorization_code" )
209
+ } else {
210
+ tok , err = parseToken ([]byte (codeOrTok ), tok )
198
211
}
199
212
213
+ if err != nil {
214
+ return tok , fmt .Errorf ("get token: %w" , err )
215
+ }
200
216
if err := g .verifyToken (p , tok , nonce ); err != nil {
201
- return tok , err
217
+ return tok , fmt . Errorf ( "verify token: %w" , err )
202
218
}
203
219
204
220
return tok , nil
205
221
}
206
222
207
223
// getToken actually gets token from Provider via wellKnown.TokenURI
208
- func (g * Goic ) getToken (p * Provider , code , redir , grant string ) (* Token , error ) {
209
- tok : = & Token {Provider : p .Name }
224
+ func (g * Goic ) getToken (p * Provider , code , redir , grant string ) (tok * Token , err error ) {
225
+ tok = & Token {Provider : p .Name }
210
226
211
227
qry := url.Values {}
212
228
qry .Add ("grant_type" , grant )
@@ -219,7 +235,7 @@ func (g *Goic) getToken(p *Provider, code, redir, grant string) (*Token, error)
219
235
qry .Add ("client_id" , p .clientID )
220
236
qry .Add ("client_secret" , p .clientSecret )
221
237
222
- req , err := http .NewRequest ("POST" , p .wellKnown . TokenURI , strings .NewReader (qry .Encode ()))
238
+ req , err := http .NewRequest ("POST" , p .GetURI ( "token" ) , strings .NewReader (qry .Encode ()))
223
239
if err != nil {
224
240
return tok , err
225
241
}
@@ -231,38 +247,41 @@ func (g *Goic) getToken(p *Provider, code, redir, grant string) (*Token, error)
231
247
}
232
248
defer res .Body .Close ()
233
249
234
- body , err := ioutil .ReadAll (res .Body )
250
+ body , err := io .ReadAll (res .Body )
235
251
if err != nil {
236
252
return tok , err
237
253
}
238
254
239
- if err := json .Unmarshal (body , & tok ); err != nil {
255
+ return parseToken (body , tok )
256
+ }
257
+
258
+ func parseToken (tokByte []byte , tok * Token ) (* Token , error ) {
259
+ if err := json .Unmarshal (tokByte , & tok ); err != nil {
240
260
return tok , err
241
261
}
262
+ if tok .IDToken == "" {
263
+ return tok , ErrTokenEmpty
264
+ }
242
265
243
266
if tok .Err != "" {
244
267
msg := tok .Err
245
268
if tok .ErrDesc != "" {
246
269
msg += ": " + tok .ErrDesc
247
270
}
248
- return tok , errors . New (msg )
271
+ return tok , fmt . Errorf (msg )
249
272
}
250
-
251
- if tok .IDToken == "" {
252
- return tok , ErrTokenEmpty
253
- }
254
-
255
273
return tok , nil
256
274
}
257
275
258
276
// verifyToken checks and verifies authenticity and ownership of Token
259
- func (g * Goic ) verifyToken (p * Provider , tok * Token , nonce string ) error {
260
- claims , err := verifyClaims ( tok , nonce , p . clientID )
261
- if err != nil {
277
+ func (g * Goic ) verifyToken (p * Provider , tok * Token , nonce string ) ( err error ) {
278
+ // Data verification
279
+ if err = tok . VerifyClaims ( nonce , p . clientID ); err != nil {
262
280
return err
263
281
}
264
282
265
- _ , err = jwt .ParseWithClaims (tok .IDToken , claims , func (t * jwt.Token ) (interface {}, error ) {
283
+ // Signature verification
284
+ _ , err = jwt .ParseWithClaims (tok .IDToken , tok .Claims , func (t * jwt.Token ) (any , error ) {
266
285
alg := t .Header ["alg" ].(string )
267
286
al2 := alg [0 :2 ]
268
287
if al2 == "HS" {
@@ -397,8 +416,11 @@ func (g *Goic) UserInfo(tok *Token) *User {
397
416
}
398
417
399
418
p := g .providers [tok .Provider ]
419
+ if p .GetURI ("userinfo" ) == "" {
420
+ return user .FromClaims (tok .Claims )
421
+ }
400
422
401
- req , err := http .NewRequest ("GET" , p .wellKnown . UserInfoURI , nil )
423
+ req , err := http .NewRequest ("GET" , p .GetURI ( "userinfo" ) , nil )
402
424
if err != nil {
403
425
return user .withError (err )
404
426
}
@@ -457,7 +479,7 @@ func (g *Goic) SignOut(tok *Token, redir string, res http.ResponseWriter, req *h
457
479
return ErrProviderSupport
458
480
}
459
481
460
- redirect , err := http .NewRequest ("GET" , p .wellKnown . SignOutURI , nil )
482
+ redirect , err := http .NewRequest ("GET" , p .GetURI ( "signout" ) , nil )
461
483
if err != nil {
462
484
return err
463
485
}
@@ -497,7 +519,7 @@ func (g *Goic) RevokeToken(tok *Token) error {
497
519
qry .Add ("token" , tk )
498
520
qry .Add ("token_type_hint" , hint )
499
521
500
- req , err := http .NewRequest ("POST" , p .wellKnown . RevokeURI , strings .NewReader (qry .Encode ()))
522
+ req , err := http .NewRequest ("POST" , p .GetURI ( "revoke" ) , strings .NewReader (qry .Encode ()))
501
523
if err != nil {
502
524
return err
503
525
}
0 commit comments