func Client(ctx context.Context, config *oauth2.Config, options ...Option) (*http.Client, *oauth2.Token, error) { o := processOpts(options) if o.filecache != nil { tok, err := o.filecache.Token() if err == nil { o.tok = tok } } if o.tok != nil { tok, err := config.TokenSource(ctx, o.tok).Token() if err == nil { return config.Client(ctx, tok), tok, nil } } tok, err := ExecuteFlow(ctx, config, options...) if err != nil { return nil, nil, err } if o.filecache != nil { _ = o.filecache.Write(tok) } return config.Client(ctx, tok), tok, nil }
func (p *Engine) _google(code string) (*User, error) { var cfg oauth2.Config if err := p.Dao.Get("google.oauth", &cfg); err != nil { return nil, err } tok, err := cfg.Exchange(oauth2.NoContext, code) if err != nil { return nil, err } cli := cfg.Client(oauth2.NoContext, tok) res, err := cli.Get("https://www.googleapis.com/oauth2/v1/userinfo?alt=json") if err != nil { return nil, err } defer res.Body.Close() var gu GoogleUser dec := json.NewDecoder(res.Body) if err := dec.Decode(&gu); err != nil { return nil, err } return p.Dao.AddUser(gu.ID, "google", gu.Email, gu.Name, gu.Link, gu.Picture) }
// facebookHandler is a ContextHandler that gets the OAuth2 Token from the ctx // to get the corresponding Facebook User. If successful, the user is added to // the ctx and the success handler is called. Otherwise, the failure handler // is called. func facebookHandler(config *oauth2.Config, success, failure ctxh.ContextHandler) ctxh.ContextHandler { if failure == nil { failure = gologin.DefaultFailureHandler } fn := func(ctx context.Context, w http.ResponseWriter, req *http.Request) { token, err := oauth2Login.TokenFromContext(ctx) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } httpClient := config.Client(ctx, token) facebookService := newClient(httpClient) user, resp, err := facebookService.Me() err = validateResponse(user, resp, err) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } ctx = WithUser(ctx, user) success.ServeHTTP(ctx, w, req) } return ctxh.ContextHandlerFunc(fn) }
func handleCallback(w http.ResponseWriter, r *http.Request, config *oauth2.Config, profilesURL, code string) { token, err := config.Exchange(oauth2.NoContext, code) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } client := config.Client(oauth2.NoContext, token) response, err := client.Get(profilesURL) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } defer response.Body.Close() rawBody, err := ioutil.ReadAll(response.Body) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } s, _ := session.Manager.SessionStart(w, r) defer s.SessionRelease(w) s.Set("id_token", token.Extra("id_token")) s.Set("access_token", token.AccessToken) s.Set("profile", string(rawBody)) http.Redirect(w, r, "/user", http.StatusMovedPermanently) }
// googleHandler is a ContextHandler that gets the OAuth2 Token from the ctx // to get the corresponding Google Userinfoplus. If successful, the user info // is added to the ctx and the success handler is called. Otherwise, the // failure handler is called. func googleHandler(config *oauth2.Config, success, failure ctxh.ContextHandler) ctxh.ContextHandler { if failure == nil { failure = gologin.DefaultFailureHandler } fn := func(ctx context.Context, w http.ResponseWriter, req *http.Request) { token, err := oauth2Login.TokenFromContext(ctx) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } httpClient := config.Client(ctx, token) googleService, err := google.New(httpClient) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } userInfoPlus, err := googleService.Userinfo.Get().Do() err = validateResponse(userInfoPlus, err) if err != nil { ctx = gologin.WithError(ctx, err) failure.ServeHTTP(ctx, w, req) return } ctx = WithUser(ctx, userInfoPlus) success.ServeHTTP(ctx, w, req) } return ctxh.ContextHandlerFunc(fn) }
func getClient(config *oauth2.Config, code string) (*drive.Service, error) { if config == nil { return nil, errors.New("Google Drive is not configured") } token := &oauth2.Token{AccessToken: code} return drive.New(config.Client(context.Background(), token)) }
// TokenOAuthClient returns an oauth2 client for a specific token func (c *client) TokenOAuthClient(ctx context.Context, config *oauth2.Config, userToken *oauth2.Token) (client *http.Client, err error) { if !userToken.Valid() { // if user token is expired userToken = &oauth2.Token{RefreshToken: userToken.RefreshToken} } return config.Client(ctx, userToken), err }
// getClient uses a Context and Config to retrieve a Token // then generate a Client. It returns the generated Client. func getSheetClient(ctx context.Context, authConfig *oauth2.Config) *http.Client { tok, err := tokenFromFile(config.SheetCredentials) if err != nil { tok = getTokenFromWeb(authConfig) saveToken(config.SheetCredentials, tok) } return authConfig.Client(ctx, tok) }
func createClient(cfg *oauth2.Config) (*http.Client, error) { tok, err := getToken(cfg) if err != nil { return nil, err } return cfg.Client(context.Background(), tok), nil }
// NewClientTokenTLS returns a client at the specified url that // authenticates all outbound requests with the given token and // tls.Config if provided. func NewClientTokenTLS(uri, token string, c *tls.Config) Client { config := new(oauth2.Config) auther := config.Client(oauth2.NoContext, &oauth2.Token{AccessToken: token}) if c != nil { auther.Transport.(*oauth2.Transport).Base = &http.Transport{TLSClientConfig: c} } return &client{auther, uri} }
// GetClient uses a Context and Config to retrieve a Token // then generate a Client. It returns the generated Client. func GetClient(ctx context.Context, config *oauth2.Config) *http.Client { cacheFile := tokenCacheFile() tok, err := tokenFromFile(cacheFile) if err != nil { tok = getTokenFromWeb(config) saveToken(cacheFile, tok) } return config.Client(ctx, tok) }
// getClient uses a Context and Config to retrieve a Token // then generate a Client. It returns the generated Client. func getClient(ctx context.Context, config *oauth2.Config) *http.Client { cacheFile := filepath.Join("./.credentials", url.QueryEscape("gmail_token.json")) token, err := tokenFromFile(cacheFile) if err != nil { log.Fatalf("Unable to retrieve token from cached credential file. %v", err) } return config.Client(ctx, token) }
// TODO: cache the twitter api call // TODO: implement OPTIONS func (l LinkerssHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { log.Printf("%+v\n", req) // TODO: has to be a cleaner pattern than this to get an int from query params numTweets := l.DefaultNumTweets numTweetsStr := req.URL.Query().Get("numTweets") if numTweetsStr != "" { var err error numTweets, err = strconv.Atoi(numTweetsStr) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(fmt.Sprintf("invalid numTweets %s", numTweetsStr))) return } } if numTweets > l.MaxNumTweets { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(fmt.Sprintf("invalid numTweets %d, must be less than %d", numTweets, l.MaxNumTweets))) return } // set up the twitter client config := oauth2.Config{} token := oauth2.Token{AccessToken: l.AccessToken} httpClient := config.Client(oauth2.NoContext, &token) client := twitter.NewClient(httpClient) // fetch the timeline screenName := req.URL.Query().Get("screenName") userTimelineParams := &twitter.UserTimelineParams{ ScreenName: screenName, Count: numTweets} tweets, _, err := client.Timelines.UserTimeline(userTimelineParams) if err != nil { log.Fatal("error getting user timeline: %v", err) } // filter down to just tweets with urls urlTweets := make([]twitter.Tweet, 0) for _, t := range tweets { if t.Entities.Urls != nil { urlTweets = append(urlTweets, t) } } // turn them into feed entries feed := tweetsToFeed(urlTweets, screenName, l.Pool) // write back to client as rss err = feed.WriteRss(w) if err != nil { log.Fatal("error outputting as rss: %v", err) } }
func newOAuthClient(ctx context.Context, config *oauth2.Config) *http.Client { cacheFile := tokenCacheFile(config) token, err := tokenFromFile(cacheFile) if err != nil { token = tokenFromWeb(ctx, config) saveToken(cacheFile, token) } else { log.Printf("Using cached token %#v from %q", token, cacheFile) } return config.Client(ctx, token) }
// getClient uses a Context and Config to retrieve a Token // then generate a Client. It returns the generated Client. func getClient(ctx context.Context, config *oauth2.Config) *http.Client { cacheFile, err := tokenCacheFile() if err != nil { log.Fatalf("Unable to get path to cached credential file. %v", err) } tok, err := tokenFromFile(cacheFile) if err != nil { tok = getTokenFromWeb(config) saveToken(cacheFile, tok) } return config.Client(ctx, tok) }
// PasswordAuthenticatedClientFromConfig handles some boilerplate for // service-to-service username/password authenticated client creation for you. // Config should likely be created by one of the convenience functions in // gog5auth/client, username and password should for the service account, and // ctx is optional. func PasswordAuthenticatedClientFromConfig(conf *oauth2.Config, username, password string, ctx context.Context) (*http.Client, error) { if ctx == nil { ctx = context.Background() } token, err := TokenForConfigAndCredentials(conf, username, password, ctx) if err != nil { return nil, err } return conf.Client(ctx, token), nil }
// NewClientTokenTLS returns a client at the specified url that authenticates // all outbound requests with the given token and tls.Config if provided. func NewClientTokenTLS(uri, token string, c *tls.Config) Client { config := new(oauth2.Config) auther := config.Client(oauth2.NoContext, &oauth2.Token{AccessToken: token}) if c != nil { if trans, ok := auther.Transport.(*oauth2.Transport); ok { trans.Base = &http.Transport{ TLSClientConfig: c, Proxy: http.ProxyFromEnvironment, } } } return &client{client: auther, base: uri, token: token} }
func Read(cfg *oauth2.Config, r io.Reader) (*http.Client, error) { t := &oauth2.Token{} b, err := ioutil.ReadAll(r) if err != nil { return nil, err } if err := decodeToken(b, t); err != nil { return nil, err } return cfg.Client(context.Background(), t), nil }
func pollOAuthConfirmation(context *cli.Context, deviceCode string, interval int) (*http.Client, string) { config := oauth2.Config{ ClientID: lib.DefaultConfig.GCPOAuthClientID, ClientSecret: lib.DefaultConfig.GCPOAuthClientSecret, Endpoint: oauth2.Endpoint{ AuthURL: lib.DefaultConfig.GCPOAuthAuthURL, TokenURL: lib.DefaultConfig.GCPOAuthTokenURL, }, RedirectURL: gcp.RedirectURL, Scopes: []string{gcp.ScopeCloudPrint}, } for { time.Sleep(time.Duration(interval) * time.Second) form := url.Values{ "client_id": {lib.DefaultConfig.GCPOAuthClientID}, "client_secret": {lib.DefaultConfig.GCPOAuthClientSecret}, "code": {deviceCode}, "grant_type": {gcpOAuthGrantTypeDevice}, } response, err := http.PostForm(gcpOAuthTokenPollURL, form) if err != nil { log.Fatalln(err) } var r struct { Error string `json:"error"` AccessToken string `json:"access_token"` ExpiresIn int `json:"expires_in"` RefreshToken string `json:"refresh_token"` } json.NewDecoder(response.Body).Decode(&r) switch r.Error { case "": token := &oauth2.Token{RefreshToken: r.RefreshToken} client := config.Client(oauth2.NoContext, token) client.Timeout = context.Duration("gcp-api-timeout") return client, r.RefreshToken case "authorization_pending": case "slow_down": interval *= 2 default: log.Fatalln(err) } } panic("unreachable") }
func getGmailService(tokens oauth2.Tokens) (*gmail.Service, error) { config := goauth2.Config{ ClientID: *CLIENT_ID, ClientSecret: *SECRET, Endpoint: google.Endpoint, Scopes: []string{gmail.MailGoogleComScope}, RedirectURL: "http://localhost:8080/auth", } ctx := context.Background() tok := (goauth2.Token)(tokens.Get()) client := config.Client(ctx, &tok) return gmail.New(client) }
// UserOAuthClient returns an oauth2 client for a specific user func (c *client) UserOAuthClient(ctx context.Context, config *oauth2.Config, userID string) (client *http.Client, err error) { var userToken *oauth2.Token if userToken, err = c.GetCachedToken(userID); err != nil { // if token for user is not cached then go through oauth2 flow if userToken, err = c.newUserToken(ctx, config, userID); err != nil { return } } if !userToken.Valid() { // if user token is expired userToken = &oauth2.Token{RefreshToken: userToken.RefreshToken} } return config.Client(ctx, userToken), err }
// getClient uses a Context and Config to retrieve a Token // then generate a Client. It returns the generated Client. func getClient(ctx context.Context, config *oauth2.Config) (*http.Client, error) { cacheFile, err := tokenCacheFile() if err != nil { return nil, fmt.Errorf("Unable to get path to cached credential file. %v", err) } tok, err := tokenFromFile(cacheFile) if err != nil { if tok, err = getTokenFromWeb(config); err != nil { return nil, err } if err = saveToken(cacheFile, tok); err != nil { return nil, err } } return config.Client(ctx, tok), nil }
// newClient creates an instance of http.Client, wrapped with OAuth credentials. func newClient(oauthClientID, oauthClientSecret, oauthAuthURL, oauthTokenURL, refreshToken string, scopes ...string) (*http.Client, error) { config := oauth2.Config{ ClientID: oauthClientID, ClientSecret: oauthClientSecret, Endpoint: oauth2.Endpoint{ AuthURL: oauthAuthURL, TokenURL: oauthTokenURL, }, RedirectURL: RedirectURL, Scopes: scopes, } token := oauth2.Token{RefreshToken: refreshToken} client := config.Client(oauth2.NoContext, &token) return client, nil }
func newOAuthClient(ctx context.Context, config *oauth2.Config) *http.Client { path := CacheDirPath + "/token" t, err := tokenFromFile(path) if err != nil { fmt.Println(err) t, err = tokenFromWeb(ctx, config) if err != nil { panic(err) } err := saveToken(path, t) if err != nil { panic(err) } } return config.Client(ctx, t) }
// Authenticate using OAuth2 password credentials func ExamplePasswordCredentials() { apiUrl := "https://api.gb1.brightbox.com" // Brightbox username and password userName := "******" password := "******" // Users can have multiple accounts, so you need to specify which one accountId := "acc-h3nbk" // These OAuth2 application credentials are public, distributed with the // cli. applicationId := "app-12345" applicationSecret := "mocbuipbiaa6k6c" // Setup OAuth2 authentication. conf := oauth2.Config{ ClientID: applicationId, ClientSecret: applicationSecret, Endpoint: oauth2.Endpoint{ TokenURL: apiUrl + "/token", }, } token, err := conf.PasswordCredentialsToken(oauth2.NoContext, userName, password) if err != nil { fmt.Println(err) } oc := conf.Client(oauth2.NoContext, token) // Setup connection to API client, err := brightbox.NewClient(apiUrl, accountId, oc) if err != nil { fmt.Println(err) return } // Get a list of servers servers, err := client.Servers() if err != nil { fmt.Println(err) return } for _, server := range servers { fmt.Printf("id:%s name:%s\n", server.Id, server.Name) } }
func (authd *authdetails) tokenisedAuth() (*brightbox.Client, error) { conf := oauth2.Config{ ClientID: authd.APIClient, ClientSecret: authd.APISecret, Scopes: infrastructureScope, Endpoint: oauth2.Endpoint{ TokenURL: authd.tokenURL(), }, } if authd.currentToken == nil { token, err := conf.PasswordCredentialsToken(oauth2.NoContext, authd.UserName, authd.password) if err != nil { return nil, err } authd.currentToken = token } oauthConnection := conf.Client(oauth2.NoContext, authd.currentToken) return brightbox.NewClient(authd.APIURL, authd.Account, oauthConnection) }
// getAccessToClientsAccount uses a Context and Config to retrieve a Token // then generate a Client. It returns the generated Client. func getAccessToClientsAccount(ctx context.Context, config *oauth2.Config) *http.Client { cacheFile, err := createTokenCacheFile() if err != nil { log.Fatalf("Unable to get path to cached credential file. %v", err) } // If the token had been saved. Get it from the file // Location: $HOME/.crendentials tok, err := getTokenFromFile(cacheFile) // if not get one if err != nil { tok = getTokenFromWeb(config) // Save it to above described location saveClientsTokenToFileInHomeDir(cacheFile, tok) } return config.Client(ctx, tok) }
// Google is a callback appropriate for use with Google's OAuth2 configuration. func Google(cfg oauth2.Config, token *oauth2.Token) (authboss.Attributes, error) { client := cfg.Client(oauth2.NoContext, token) resp, err := clientGet(client, googleInfoEndpoint) if err != nil { return nil, err } defer resp.Body.Close() dec := json.NewDecoder(resp.Body) var jsonResp googleMeResponse if err = dec.Decode(&jsonResp); err != nil { return nil, err } return authboss.Attributes{ authboss.StoreOAuth2UID: jsonResp.ID, authboss.StoreEmail: jsonResp.Email, }, nil }
// Perform the full authentication flow. func Auth( cfg *oauth2.Config, filename string, f func(string) error) (*http.Client, error) { if c, err := ReadFile(cfg, filename); err == nil { return c, nil } t, err := auth(cfg, f) if err != nil { return nil, err } if err := saveFile(t, filename); err != nil { return nil, err } return cfg.Client(context.Background(), t), nil }
// Facebook is a callback appropriate for use with Facebook's OAuth2 configuration. func Facebook(ctx context.Context, cfg oauth2.Config, token *oauth2.Token) (authboss.Attributes, error) { client := cfg.Client(ctx, token) resp, err := clientGet(client, facebookInfoEndpoint) if err != nil { return nil, err } defer resp.Body.Close() dec := json.NewDecoder(resp.Body) var jsonResp facebookMeResponse if err = dec.Decode(&jsonResp); err != nil { return nil, err } return authboss.Attributes{ "name": jsonResp.Name, authboss.StoreOAuth2UID: jsonResp.ID, authboss.StoreEmail: jsonResp.Email, }, nil }