@@ -325,7 +325,7 @@ func WaitForCallback(clientConfig ClientConfig, serverConfig ServerConfig, hc *h
325325
326326type TokenResponse struct {
327327 AccessToken string `json:"access_token,omitempty"`
328- ExpiresIn int64 `json:"expires_in,omitempty"`
328+ ExpiresIn FlexibleInt64 `json:"expires_in,omitempty"`
329329 IDToken string `json:"id_token,omitempty"`
330330 IssuedTokenType string `json:"issued_token_type,omitempty"`
331331 RefreshToken string `json:"refresh_token,omitempty"`
@@ -334,12 +334,49 @@ type TokenResponse struct {
334334 AuthorizationDetails []map [string ]interface {} `json:"authorization_details,omitempty"`
335335}
336336
337+ // FlexibleInt64 is a type that can be unmarshaled from a JSON number or
338+ // string. This was added to support the `expires_in` field in the token
339+ // response. Typically it is expressed as a JSON number, but at least
340+ // login.microsoft.com returns the number as a string.
341+ type FlexibleInt64 int64
342+
343+ func (f * FlexibleInt64 ) UnmarshalJSON (b []byte ) error {
344+ if len (b ) == 0 {
345+ return fmt .Errorf ("cannot unmarshal empty int" )
346+ }
347+
348+ // check if we have a number in a string, and parse it if so
349+ if b [0 ] == '"' {
350+ var s string
351+ if err := json .Unmarshal (b , & s ); err != nil {
352+ return err
353+ }
354+
355+ i , err := strconv .ParseInt (s , 10 , 64 )
356+ if err != nil {
357+ return err
358+ }
359+
360+ * f = FlexibleInt64 (i )
361+ return nil
362+ }
363+
364+ // finally we assume that we have a number that's not wrapped in a string
365+ var i int64
366+ if err := json .Unmarshal (b , & i ); err != nil {
367+ return err
368+ }
369+
370+ * f = FlexibleInt64 (i )
371+ return nil
372+ }
373+
337374func NewTokenResponseFromForm (f url.Values ) TokenResponse {
338375 expiresIn , _ := strconv .ParseInt (f .Get ("expires_in" ), 10 , 64 )
339376
340377 return TokenResponse {
341378 AccessToken : f .Get ("access_token" ),
342- ExpiresIn : expiresIn ,
379+ ExpiresIn : FlexibleInt64 ( expiresIn ) ,
343380 IDToken : f .Get ("id_token" ),
344381 IssuedTokenType : f .Get ("issued_token_type" ),
345382 RefreshToken : f .Get ("refresh_token" ),
0 commit comments