forked from Mirrors/oauth2
Docs, code cleanups.
This commit is contained in:
parent
eb7270d354
commit
a9dc52b3d3
41
oauth2.go
41
oauth2.go
|
@ -14,16 +14,17 @@ import (
|
|||
"mime"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type tokenRespBody struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
TokenType string `json:"token_type"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
ExpiresIn time.Duration `json:"expires_in"`
|
||||
IdToken string `json:"id_token"`
|
||||
AccessToken string `json:"access_token"`
|
||||
TokenType string `json:"token_type"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
ExpiresIn int64 `json:"expires_in"` // in seconds
|
||||
IdToken string `json:"id_token"`
|
||||
}
|
||||
|
||||
// TokenFetcher refreshes or fetches a new access token from the
|
||||
|
@ -63,7 +64,15 @@ type Options struct {
|
|||
// Optional, identifies the level of access being requested.
|
||||
Scopes []string `json:"scopes"`
|
||||
|
||||
// Optional, "online" (default) or "offline", no refresh token if "online"
|
||||
// AccessType is an OAuth extension that gets sent as the
|
||||
// "access_type" field in the URL from AuthCodeURL.
|
||||
// See https://developers.google.com/accounts/docs/OAuth2WebServer.
|
||||
// It may be "online" (the default) or "offline".
|
||||
// If your application needs to refresh access tokens when the
|
||||
// user is not present at the browser, then use offline. This
|
||||
// will result in your application obtaining a refresh token
|
||||
// the first time your application exchanges an authorization
|
||||
// code for a user.
|
||||
AccessType string `json:"omit"`
|
||||
|
||||
// ApprovalPrompt indicates whether the user should be
|
||||
|
@ -187,8 +196,9 @@ func (c *Config) validate() error {
|
|||
func (c *Config) Exchange(exchangeCode string) (*Token, error) {
|
||||
token := &Token{}
|
||||
vals := url.Values{
|
||||
"grant_type": {"authorization_code"},
|
||||
"code": {exchangeCode},
|
||||
"grant_type": {"authorization_code"},
|
||||
"client_secret": {c.opts.ClientSecret},
|
||||
"code": {exchangeCode},
|
||||
}
|
||||
if len(c.opts.Scopes) != 0 {
|
||||
vals.Set("scope", strings.Join(c.opts.Scopes, " "))
|
||||
|
@ -203,9 +213,15 @@ func (c *Config) Exchange(exchangeCode string) (*Token, error) {
|
|||
return token, nil
|
||||
}
|
||||
|
||||
// updateToken mutates both tok and v.
|
||||
func (c *Config) updateToken(tok *Token, v url.Values) error {
|
||||
v.Set("client_id", c.opts.ClientID)
|
||||
v.Set("client_secret", c.opts.ClientSecret)
|
||||
// Note that we're not setting v's client_secret to t.ClientSecret, due
|
||||
// to https://code.google.com/p/goauth2/issues/detail?id=31
|
||||
// Reddit only accepts client_secret in Authorization header.
|
||||
// Dropbox accepts either, but not both.
|
||||
// The spec requires servers to always support the Authorization header,
|
||||
// so that's all we use.
|
||||
r, err := http.DefaultClient.PostForm(c.tokenURL.String(), v)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -231,15 +247,12 @@ func (c *Config) updateToken(tok *Token, v url.Values) error {
|
|||
resp.AccessToken = vals.Get("access_token")
|
||||
resp.TokenType = vals.Get("token_type")
|
||||
resp.RefreshToken = vals.Get("refresh_token")
|
||||
resp.ExpiresIn, _ = time.ParseDuration(vals.Get("expires_in") + "s")
|
||||
resp.ExpiresIn, _ = strconv.ParseInt(vals.Get("expires_in"), 10, 64)
|
||||
resp.IdToken = vals.Get("id_token")
|
||||
default:
|
||||
if err = json.NewDecoder(r.Body).Decode(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
// The JSON parser treats the unitless ExpiresIn like 'ns' instead of 's' as above,
|
||||
// so compensate here.
|
||||
resp.ExpiresIn *= time.Second
|
||||
}
|
||||
tok.AccessToken = resp.AccessToken
|
||||
tok.TokenType = resp.TokenType
|
||||
|
@ -250,7 +263,7 @@ func (c *Config) updateToken(tok *Token, v url.Values) error {
|
|||
if resp.ExpiresIn == 0 {
|
||||
tok.Expiry = time.Time{}
|
||||
} else {
|
||||
tok.Expiry = time.Now().Add(resp.ExpiresIn)
|
||||
tok.Expiry = time.Now().Add(time.Duration(resp.ExpiresIn) * time.Second)
|
||||
}
|
||||
if resp.IdToken != "" {
|
||||
if tok.Extra == nil {
|
||||
|
|
|
@ -30,6 +30,10 @@ type Token struct {
|
|||
// The remaining lifetime of the access token.
|
||||
Expiry time.Time `json:"expiry,omitempty"`
|
||||
|
||||
// Extra optionally contains extra metadata from the server
|
||||
// when updating a token. The only current key that may be
|
||||
// populated is "id_token". It may be nil and will be
|
||||
// initialized as needed.
|
||||
Extra map[string]string `json:"extra,omitempty"`
|
||||
|
||||
// JWT related fields
|
||||
|
|
Loading…
Reference in New Issue