Coder Social home page Coder Social logo

oauth2's Introduction

OAuth2 for Go

Go Reference Build Status

oauth2 package contains a client implementation for OAuth 2.0 spec.

Installation

go get golang.org/x/oauth2

Or you can manually git clone the repository to $(go env GOPATH)/src/golang.org/x/oauth2.

See pkg.go.dev for further documentation and examples.

Policy for new endpoints

We no longer accept new provider-specific packages in this repo if all they do is add a single endpoint variable. If you just want to add a single endpoint, add it to the pkg.go.dev/golang.org/x/oauth2/endpoints package.

Report Issues / Send Patches

The main issue tracker for the oauth2 repository is located at https://github.com/golang/oauth2/issues.

This repository uses Gerrit for code changes. To learn how to submit changes to this repository, see https://golang.org/doc/contribute.html. In particular:

  • Excluding trivial changes, all contributions should be connected to an existing issue.
  • API changes must go through the change proposal process before they can be accepted.
  • The code owners are listed at dev.golang.org/owners.

oauth2's People

Contributors

adg avatar aeitzman avatar andyrzhao avatar bigtailwolf avatar bradfitz avatar broady avatar cnbuff410 avatar codyoss avatar cuishuang avatar ericchiang avatar fenwickelliott avatar foxxtrot avatar githuriel avatar gopherbot avatar hickford avatar maddyblue avatar narqo avatar nkprince007 avatar odeke-em avatar okdave avatar proppy avatar quartzmo avatar rakyll avatar rsc avatar samwhited avatar scruffyprodigy avatar seanrees avatar tcolgate avatar voutasaurus avatar zombiezen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oauth2's Issues

Options.Scopes should be omitempty

The Options.Scopes field should probably be "scopes,omitempty".

And its doc style should be more like "Scopes optionally specifies a list of requested permission scopes."

invalid_grant

Using the same credentials & .pem that are working in other googleapi libraries with example_test.go Example_jWTConfig, I am getting "invalid_grant", and "Cannot fetch token, response: 400 Bad Request" errors.

The only things I'm not 100% confident about are how the PrivateKey is meant to be passed, and what audURL is expected to be. I'm currently reading the .pem w/ ioutil, assigning the []byte result of that to the JWTOptions.PrivateKey, and passing "https://accounts.google.com/o/oauth2/token" as the aud argument.

Helper function to decode id_token

The jws package can decode the id_token, but only the standard fields (I think it is).

Specifically I am missing an easy way to decode the email and email_verified from the google oauth2 service.

Currently I am just duplicating the base64 padding and base64 + json decoding, but that seems pretty goofy when it's already ... almost ... done.

It looks like there's some support for this in jws (PrivateClaims), but not for decoding.

How are we supposed to use appenginevm.go?

I was trying to use it in my managed vm project by doing standard "go get" way, and there are two issues

1 When I try to deploy my code, it always compile appengine.go instead of appenginevm.go and complains about the lack of "appengine" import. I have to manually remove appengine.go, and then remove the build tag in appenginevm.go, to make the compilation happy.

2 Then I get the client and send it to storage api, and get error "x509: failed to load system roots and no roots provided". It was working when I used the old oauth2 code on code.google.com. Here is the code I tried:

    config := google.NewAppEngineConfig(context, []string{
        "https://www.googleapis.com/auth/devstorage.read_only"})
    client := http.Client{Transport: config.NewTransport()}
    service, err := storage.New(&client)

Latest version stopped working: undefined oauth2.New

Together with a friend of mine we're doing a small app that uses oauth2. I started development around week ago and everything cracked. He joined me yesterday and because we didn't lock the dependencies, he fetched the latest version of the library which causes following errors to occur when starting the server:

# command-line-arguments
./test.go:10: undefined: oauth2.New
./test.go:11: undefined: oauth2.Client
./test.go:12: undefined: oauth2.RedirectURL
./test.go:13: undefined: oauth2.Scope
./test.go:17: cannot call non-function google.Endpoint (type oauth2.Endpoint)
./test.go:21: undefined: oauth2.Client

I fetched the latest version and I get exactly the same errors. We figured out that the last version that worked is 3ec35f1969392f03bef5d4032463c3e33cc9f9e5.

We both use OS X 10.10 & Go 1.4.

google: Support service account JSON key file

Google Developers Console now allows you to download the generated private key and service account email bundled in a JSON file. We should support this file rather than requiring user to convert p12 to pem.

LinkedIn OAuth2 Login fails to get token, requires client_secret as parameter

LinkedIn fails on retrieveToken ("https://www.linkedin.com/uas/oauth2/accessToken")
Returns this:

{"error_description":"missing required parameters, includes an invalid parameter value, parameter more than once. : client_secret","error":"invalid_request"}

This change introduced the problem:
bb84968

Linkedin needs to be added to the list of busted auths in providerAuthHeaderWorks function. They require "client_secret" as a parameter, instead of taking it as basic auth header. Please add linkedin to the list (https://www.linkedin.com/), or give users some way to manually add oauth2 providers

Caches should be Transport implementations

@proppy gave some feedback about caching. Cache interface doesn't have flexibility to support multiple users. Rather than providing another Cache interface with token identification such as

type Cache interface {
    Read(id interface{}) (*Token, error)
    Write(id interface{}, token *Token) error
}

we should wrap the authorizedTransport with a cacher transport.

t := FileCacheTransport{config.NewAuthorizedTransport()}

FileCacheTransport's RoundTripper could handle token caching.

Issue with appengine urlfetch

I'm getting the following error with appengine. Same issue with go 1.4beta on appengine.
golang.org/x/oauth2/client_appengine.go:28: undefined: urlfetch.NewClient

urlfetch has a function called Client.

Package assumes fields not required by RFC6749 required

  • Auth Code URI generator assumes the following optional or recommended fields are required.
    • redirect_uri and scope are optional. state is recommended therefore should be optional.
    • client_secret is allowed by the spec to be an empty string.
  • Access Token Request:
    • redirect_uri is required only if Auth Code URI contained it. So, the package should assume that it's optional and misuse should be handled by the server.
    • client_secret is allowed by the spec to be an empty string.
  • Refresh Token Request:
    • Only grant_type and refresh_token is required.
    • "The requested scope MUST NOT include any scope not originally granted by the resource owner." We dont know which scopes refresh token is already authorised for during auto refresh. We can fix the interfaces to allow additional scopes on manual refresh.
  • Validation shouldn't assume client_secret is missing if it's an empty string.

oauth2 is not compatible with Go 1.2?

I'm using Managed VM Go runtime and it still only supports 1.2.2 . When I compile the code I got following error:

unknown net.Dialer field 'KeepAlive' in struct literal

I searched online a little bit and seems like it's Go pre1.2 issue. Go 1.3 fixed it, but not supported by Managed VM yet.

Any suggestion on workaround or I have to wait for 1.3 support?

Add support for javascript oauth2 scenario

I have a particular case where I got the access token using a Javascript client-side scenario (https://developers.google.com/accounts/docs/OAuth2, https://developers.google.com/accounts/docs/OAuth2UserAgent). When my backend receives the token, I need to check if it is valid and if is for my clientID (No client secret here), then use it to perform requests.

I was not able to get this package to work in such scenario. I tried using TokenStore, but it gave me "oauth2: missing endpoints, can't determine how to fetch tokens".

Maybe this is a scenario you guys would like to support.

Check PayPal and VKontakte

Hi guys,

I've just stumbled upon your lib and it seems active and most code reused from goauth2.
So, may I ask you to review my small changes for goauth2, that I make to use it with LinkedIn, PayPal and VKontakte and to decide if they are relevant for your lib?

Here is the diff: https://code.google.com/r/nikolay-goauth2/source/diff?spec=svn90e22c7acbc4a815996ec16c939f11f83a4abf6c&r=90e22c7acbc4a815996ec16c939f11f83a4abf6c&format=side&path=/oauth/oauth.go

Your Transport.RoundTrip() method seems to take care of issue with "Authorization" header for LinkedIn a way better then mine, but other issues may still affect your code. As I remember causes of those changes: PayPal's "expires_in" field was a string (not a number) and won't decode from json well and VKontakte returns extra uesful "user_id" field (in response to retrieve token request).

I made changes some 10 month ago and cannot provide better explanations (also things may change already), but changed code is in production and seems to work.

Sorry, cannot test your lib myself yet.

support for parsing Google's client_secret.json

After setting up a new credential in https://console.developers.google.com, you're given an option to "Download JSON" credentials, which results in a file of the form:

{
  "installed": {
    "auth_uri":"https://accounts.google.com/o/oauth2/auth",
    "client_secret":"REDACTED",
    "token_uri":"https://accounts.google.com/o/oauth2/token",
    "client_email":"",
    "redirect_uris":["urn:ietf:wg:oauth:2.0:oob","oob"],
    "client_x509_cert_url":"",
    "client_id":"REDACTED",
    "auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs"
  }
}

As far as I know this isn't a standard format, but I would have expected something in the google package to parse this into an oauth2.Config, somewhat similar to google.JWTConfigFromJSON. So is the expectation simply that you don't use that downloaded JSON file? Any reason not to support that?

Can't obtain other fields (e.g., granted scopes) associated with access token

Some OAuth2 provider implementations include additional fields with the access token.

For example, on GitHub, soon users will be able to edit the scope they grant to applications. This means that an access token's scope might not match what was requested by the application. To determine the actual granted scope, the application should read the scope property returned alongside the access token from that endpoint. See the GitHub API docs, "Requested scopes vs. granted scopes".

The code at

oauth2/oauth2.go

Lines 251 to 271 in 38c4892

token := &Token{
AccessToken: resp.AccessToken,
TokenType: resp.TokenType,
RefreshToken: resp.RefreshToken,
}
// Don't overwrite `RefreshToken` with an empty value
// if this was a token refreshing request.
if resp.RefreshToken == "" {
token.RefreshToken = v.Get("refresh_token")
}
if resp.ExpiresIn == 0 {
token.Expiry = time.Time{}
} else {
token.Expiry = time.Now().Add(time.Duration(resp.ExpiresIn) * time.Second)
}
if resp.IdToken != "" {
if token.Extra == nil {
token.Extra = make(map[string]string)
}
token.Extra["id_token"] = resp.IdToken
}
does not allow access to these additional fields (such as scope). The workaround is to wrap the OAuth2 transport and extract it that way, but that's complicated. Should (c *Config) retrieveToken be modified to add extra fields as properties on the Extra map?

Google Cloud docs use old API

The example of using oauth2 to access Google Cloud Storage from an App Engine application [https://cloud.google.com/appengine/docs/go/googlecloudstorageclient/getstarted] does not align with this library's methods.

Add possibility to set deadline on GAE urlfetch.Transports

I originally switched from https://code.google.com/p/goauth2 to this library because it provided the possibility to set the Deadline property of urlfetch.Transport, which is essential when dealing with larger files on GCS.
Unfortunately this is no longer possible in the current implementation with just the one function

func AppEngineContext(ctx appengine.Context) oauth2.Option

I propose a new function to supplement or even replace AppEngineContext():

func AppEngineTransport(trans *urlfetch.Transport) oauth2.Option {
    return func(opts *oauth2.Options) error {
        opts.TokenFetcherFunc = makeAppEngineTokenFetcher(trans.Context, opts)
        opts.Client = &http.Client{
            Transport: trans,
        }
        return nil
    }
}    

make it easy to create an *http.Client from the google package

Tracking bug to make the golang.org/x/oauth2/google package have funcs to return *http.Clients in addition to the TokenSource ones.

And/or maybe we should (in the oauth2 package) have:

package oauth2
func NewClient(ctx Context, src TokenSource) *http.Client { ... }

... which uses the unexported func contextTransport.

/cc @adg

Move google package elsewhere

We need to remove the non-spec bits from the oauth2 tree, we might rather have a google.golang.org package to provide Google related options.

does TokenFetcher mutate its argument?

The type TokenFetcher doesn't document whether it's expected to mutate its input parameter.

That seemed counter-intuitive that the input was mutated and then returned. Seemed unnecessary to even return it if that's the way they're expected to work.

Also I wasn't sure at first whether existing could be nil. It seems like that's never allowed.

use variadics for scope arguments throughout

Something very minor I just stumbled upon while using the package for the first time.

func NewAppEngineConfig(context appengine.Context, scopes []string) *AppEngineConfig
-> scopes given as slice

NewServiceAccountJSONConfig(filename string, scopes ...string) (*oauth2.JWTConfig, error)
-> scopes given as variadic argument

Should be identical imho. I'd prefer slices.

Remove Auth Code URI options from oauth2.Options

access_type and approval_prompt are optional query parameters to append to the Auth Code URI. They shouldn't be set at the Config level. (*Config).AuthCodeURL can ask for additional arguments.

expires_in taking precedence over expires

It seems that expires_in values are taking precedence of expires values, which seems incorrect to me. expires should be the canonical value that the provider stores, using expires_in with a time.Now() call will create a value that is incorrect by the time from the provider creating the token, and the consumer processing the response.

Happy to swap them about and create a PR, just wanted to check and see if there's a reason I'm not aware of?

Why is newTransportFromToken not exported?

Hi!

I am using oauth2 in a project, and am currently storing the marshalled Tokens.

It would be nice if I could just unmarshall those tokens, and then call newTransportFromToken, but I assume it is not exported for a specific reason?

I can't seem to find a way to take a single token, and create a transport from it currently. Is there a suggested way to do that? I looked a little bit at ReadToken from the TokenStore, but that would only be helpful if I had a TokenStore per user (which doesn't seem right?) thanks!

Provide means to load private key from custom sources

Currently oauth.JWTOptions has a PemFilename field that oauth.NewJWTConfig uses to read in the key. It's likely that people will want to supply their own key mechanism. Maybe there should be another field PemKey []byte which is used if non-nil.

Support request cancellation

I think it would be nice if the oauth2.Transport supported request cancellation when the underlying http.RoundTripper does. It was brought up in the #8 discussion, but it's a separate issue. This is required to support Timeout in an http.Client.

I made a proof of concept a while back and would be willing to contribute updated code if desired. Please ignore all the TokenStore interface bits. The relevant part is that oauth2.Transport is an interface and the constructor returns a specific implementation depending on the http.RoundTripper implementation. I'm not sure if other people want this, if it's important that the oauth2.Transport not be an interface, or if there's too much "magic" going on.

Support Dockerized access to metadata server

Because the metadata server host for GCE is hardcoded in

u := "http://metadata/computeMetadata/v1/instance/service-accounts/" + account + "/token"
, this library can't use service accounts from within Docker. If attempted, it throws the following error:

Get http://metadata/computeMetadata/v1/instance/service-accounts/default/token dial tcp: lookup metadata: no such host

If the hardcoding is switched to metadata.google.internal, or if the host is something that can be passed through the ComputeEngineConfig struct, then this library becomes usable within Docker.

I'm happy to open a pull request for either of these options.

Move Options type to a separate package

Exporting the Options type from the oauth2 package is likely to confuse the end-user. The Option types contributor has to know about the separate package, but the end-user doesn't have to.

Can't Add Multiple Scopes for App Engine

// Should provide multiple scopes
config := google.NewAppEngineConfig(c, []string{
        "https://www.googleapis.com/auth/bigquery",
        "https://www.googleapis.com/auth/devstorage.full_control",
        "https://www.googleapis.com/auth/cloud-platform",
    })
// Causes this error
recover from panic situation: - runtime error: invalid memory address or nil pointer dereference
// In the logs, it shows
API error 9 (app_identity_service: UNKNOWN_SCOPE)

// Same structure, but only requests a single scope - works perfectly
config := google.NewAppEngineConfig(c, []string{
        "https://www.googleapis.com/auth/devstorage.full_control",
    })

I tried following the scope creation through the NewAppEngineConfig process, and it shows that in AuthCodeURL, it joins the scopes together with spaces. When I try passing through multiple scopes in the first string space delimited, it gives me the same error and passing through a slice of scope strings.

// NewAppEngineConfig creates a new AppEngineConfig for the
// provided auth scopes.
func NewAppEngineConfig(context appengine.Context, scopes []string) *AppEngineConfig {
    return &AppEngineConfig{context: context, scopes: scopes}
}

// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
// that asks for permissions for the required scopes explicitly.
func (c *Config) AuthCodeURL(state string) (authURL string) {
    u := *c.authURL
    q := url.Values{
        "response_type":   {"code"},
        "client_id":       {c.opts.ClientID},
        "redirect_uri":    {c.opts.RedirectURL},
        "scope":           {strings.Join(c.opts.Scopes, " ")},
        "state":           {state},
        "access_type":     {c.opts.AccessType},
        "approval_prompt": {c.opts.ApprovalPrompt},
    }.Encode()
    if u.RawQuery == "" {
        u.RawQuery = q
    } else {
        u.RawQuery += "&" + q
    }
    return u.String()
}

I _think_ the build comment in appenginevm.go is incorrect?

It is // +build appenginevm !appengine

but I think it should be // +build appenginevm,!appengine (note the comma)

I'm currently using this code in a compute-engine (non-appengine and non-appenginevm) environment, so I haven't included google.golang.org/appengine. I don't think I should need to include it. By AND'ing the two build conditions, the appenginevm.go file is excluded from the build. FWIW, the two build conditions are AND'ed in appengine.go.

AuthCodeURL() modifies flow's URL instead of creating a new object

The most recent commit (0cf6f9b) introduced an undocumented change to AuthCodeURL() semantics. I expected it just to generate a new url string based on the information stored in flow, but it actually changes the state of the flow object otself.

In order to allow users to login with their Google accounts, I use the following approach:

// Upon initialization of the web server
config, err := oauth2.NewConfig(...)
...
// For each incoming connect request
authUrl := config.AuthCodeURL(...)
...
// Handle the oauth2callback, etc.

That is, I've created a global config just once, and then used it for different connection requests for Google provider.

Recently, after updating my app and the dependencies, I've discovered that the approach does not work (actually, it works, but not as I expected):

// Upon initialization of the web server
flow, err := oauth2.New(...)
...
// For each incoming connect request
authUrl := flow.AuthCodeURL(...)
...
// Handle the oauth2callback, etc.

Again, I create once a global variable flow for google provider, and for every incoming connection request, I execute flow.AuthCodeURL() to generate a new url.

The code works for the first request. However starting from the second request the code won't work.

The reason for this behavior is that every time AuthCodeURL() it modifies the flow's AuthURL field. In previous implementation, the original flow's authURL remained unchanged. For more deatails see 0cf6f9b#diff-eb12cee32bcf605b68363a07e95e0174R149

My questions are:

  • was this change done intentionally?
  • if yes, why was it necessary? and shouldn't the fact that the state of flow object is changed be documented?

Parse Config.AuthURL in advance

image

u, err := url.Parse(c.authURL)

If you validate if authUrl is parsable in validate() (

func (c *Config) validate() error {
) AuthCodeURL methods signature can be error-less, which is more practical to use.

Since Config.authURL is not accessible from other packages, this check is safe to make at NewConfig.

edit: realized the TODO here https://github.com/golang/oauth2/blob/7935ece62b5df7d253af014bd27b272c4ba62587/oauth2.go#L179-180 yeah it certainly would help

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.