// getToken returns the token saved in the config file under // section name. func getToken(name string) (*oauth2.Token, error) { tokenString, err := fs.ConfigFile.GetValue(string(name), ConfigToken) if err != nil { return nil, err } if tokenString == "" { return nil, fmt.Errorf("Empty token found - please run rclone config again") } token := new(oauth2.Token) err = json.Unmarshal([]byte(tokenString), token) if err != nil { return nil, err } // if has data then return it if token.AccessToken != "" && token.RefreshToken != "" { return token, nil } // otherwise try parsing as oldToken oldtoken := new(oldToken) err = json.Unmarshal([]byte(tokenString), oldtoken) if err != nil { return nil, err } // Fill in result into new token token.AccessToken = oldtoken.AccessToken token.RefreshToken = oldtoken.RefreshToken token.Expiry = oldtoken.Expiry // Save new format in config file err = putToken(name, token) if err != nil { return nil, err } return token, nil }
func encodeToken(referal *url.URL, outhToken *oauth2.Token) error { str := outhToken.Extra("expires_in") expiresIn, err := strconv.Atoi(fmt.Sprintf("%v", str)) if err != nil { return errs.WithStack(errors.New("cant convert expires_in to integer " + err.Error())) } str = outhToken.Extra("refresh_expires_in") refreshExpiresIn, err := strconv.Atoi(fmt.Sprintf("%v", str)) if err != nil { return errs.WithStack(errors.New("cant convert refresh_expires_in to integer " + err.Error())) } tokenData := &app.TokenData{ AccessToken: &outhToken.AccessToken, RefreshToken: &outhToken.RefreshToken, TokenType: &outhToken.TokenType, ExpiresIn: &expiresIn, RefreshExpiresIn: &refreshExpiresIn, } b, err := json.Marshal(tokenData) if err != nil { return errs.WithStack(errors.New("cant marshal token data struct " + err.Error())) } parameters := url.Values{} parameters.Add("token", outhToken.AccessToken) // Temporary keep the old "token" param. We will drop this param as soon as UI adopt the new json param. parameters.Add("token_json", string(b)) referal.RawQuery = parameters.Encode() return nil }
func (c *Client) DelegationToken(token *oauth2.Token, apiType string) (string, error) { body, err := json.Marshal(map[string]interface{}{ "client_id": c.ClientID, "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", "id_token": token.Extra("id_token"), "target": c.ClientID, "scope": "openid name email", "api_type": apiType, }) if err != nil { return "", err } url := fmt.Sprintf(delegationEndpoint, c.Domain) req, err := http.NewRequest("POST", url, bytes.NewBuffer(body)) if err != nil { return "", err } req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", c.Token)) req.Header.Set("Content-Type", "application/json") resp, err := new(http.Client).Do(req) if err != nil { return "", err } raw, err := ioutil.ReadAll(resp.Body) defer resp.Body.Close() if err != nil { return "", err } var obj map[string]interface{} if err := json.Unmarshal(raw, &obj); err != nil { return "", err } return obj["id_token"].(string), nil }
// 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 }
func (a *app) handleCallback(w http.ResponseWriter, r *http.Request) { if errMsg := r.FormValue("error"); errMsg != "" { http.Error(w, errMsg+": "+r.FormValue("error_description"), http.StatusBadRequest) return } if state := r.FormValue("state"); state != exampleAppState { http.Error(w, fmt.Sprintf("expected state %q got %q", exampleAppState, state), http.StatusBadRequest) return } code := r.FormValue("code") refresh := r.FormValue("refresh_token") var ( err error token *oauth2.Token ) oauth2Config := a.oauth2Config(nil) switch { case code != "": token, err = oauth2Config.Exchange(a.ctx, code) case refresh != "": t := &oauth2.Token{ RefreshToken: refresh, Expiry: time.Now().Add(-time.Hour), } token, err = oauth2Config.TokenSource(r.Context(), t).Token() default: http.Error(w, fmt.Sprintf("no code in request: %q", r.Form), http.StatusBadRequest) return } if err != nil { http.Error(w, fmt.Sprintf("failed to get token: %v", err), http.StatusInternalServerError) return } rawIDToken, ok := token.Extra("id_token").(string) if !ok { http.Error(w, "no id_token in token response", http.StatusInternalServerError) return } idToken, err := a.verifier.Verify(r.Context(), rawIDToken) if err != nil { http.Error(w, fmt.Sprintf("Failed to verify ID token: %v", err), http.StatusInternalServerError) return } var claims json.RawMessage idToken.Claims(&claims) buff := new(bytes.Buffer) json.Indent(buff, []byte(claims), "", " ") renderToken(w, a.redirectURI, rawIDToken, token.RefreshToken, buff.Bytes()) }
func newTokenFromRefreshToken(refreshToken string) (*oauth2.Token, error) { token := new(oauth2.Token) token.RefreshToken = refreshToken token.Expiry = time.Now() // TokenSource will refresh the token if needed (which is likely in this // use case) oauthConfig := *googleOauthConfig ts := oauthConfig.TokenSource(oauth2.NoContext, token) return ts.Token() }
// Utility method which gets the AWS credentials for the given OAuth token func FetchCredentialsForToken(w http.ResponseWriter, r *http.Request, token *oauth2.Token, rawQuery string) { user, err := GetUserFromGoogleOauthToken(token.Extra("id_token").(string)) if err != nil { log.Printf("failed to parse google id_token: %s", err) http.Error(w, "Bad Request", http.StatusBadRequest) return } groups, err := GetUserGroups(user) if err != nil { log.Printf("failed to fetch google group membership for %s: %s", user, err) http.Error(w, "Bad Request", http.StatusBadRequest) return } policy, err := MapUserAndGroupsToPolicy(user, groups) if err != nil { log.Printf("failed to determine policy for %s: %s", user, err) http.Error(w, "Bad Request", http.StatusBadRequest) return } if policy == nil { log.Printf("no matching policy for %s", user) http.Error(w, "Bad Request", http.StatusBadRequest) return } credentials, err := GetCredentials(user, policy.Policy, time.Second*43200) if err != nil { log.Printf("failed to get credentials for %s: %s", user, err) http.Error(w, "Bad Request", http.StatusBadRequest) return } query, err := url.ParseQuery(rawQuery) if err != nil { log.Printf("ERROR: parse query: %s", err) http.Error(w, "Bad Request", http.StatusBadRequest) return } fmt.Printf("login %s from %s with policy %s key %s\n", user, getRemoteAddress(r), policy.Name, credentials.AccessKeyId) RespondWithCredentials(w, r, credentials, query, token) }
// 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 }
func GetSpotifyClient(clientID, clientSecret, refreshToken string) *spotify.Client { // So as not to introduce a web flow into this program, we cheat a bit here // by just using a refresh token and not an access token (because access // tokens expiry very quickly and are therefore not suitable for inclusion // in configuration). This will force a refresh on the first call, but meh. token := new(oauth2.Token) token.Expiry = time.Now().Add(time.Second * -1) token.RefreshToken = refreshToken // See comment above. We've already procured the first access/refresh token // pair outside of this program, so no redirect URL is necessary. authenticator := spotify.NewAuthenticator("no-redirect-url") authenticator.SetAuthInfo(clientID, clientSecret) client := authenticator.NewClient(token) return &client }
// decodeToken parses an access token, refresh token, and optional // expiry unix timestamp separated by spaces into an oauth2.Token. // It returns as much as it can. func decodeToken(encoded string) *oauth2.Token { t := new(oauth2.Token) f := strings.Fields(encoded) if len(f) > 0 { t.AccessToken = f[0] } if len(f) > 1 { t.RefreshToken = f[1] } if len(f) > 2 && f[2] != "0" { sec, err := strconv.ParseInt(f[2], 10, 64) if err == nil { t.Expiry = time.Unix(sec, 0) } } return t }
// cachedToken returns the token saved in cacheFile. It specifically returns // errTokenExpired if the token is expired. func cachedToken(cacheFile string) (*oauth2.Token, error) { tok := new(oauth2.Token) tokenData, err := wkfs.ReadFile(cacheFile) if err != nil { return nil, err } if err = json.Unmarshal(tokenData, tok); err != nil { return nil, err } if !tok.Valid() { if tok != nil && time.Now().After(tok.Expiry) { return nil, errExpiredToken } return nil, errors.New("invalid token") } return tok, nil }
func getTokenContainer(ctx *gin.Context) (*TokenContainer, bool) { var oauth_token *oauth2.Token var tc *TokenContainer var err error if oauth_token, err = extractToken(ctx.Request); err != nil { glog.Errorf("Can not extract oauth2.Token, caused by: %s", err) return nil, false } if !oauth_token.Valid() { glog.Infof("Invalid Token - nil or expired") return nil, false } if tc, err = GetTokenContainer(oauth_token); err != nil { glog.Errorf("Can not extract TokenContainer, caused by: %s", err) return nil, false } return tc, true }
// people fetches the list of people user has shared with this app func people(w http.ResponseWriter, r *http.Request) *appError { session, err := store.Get(r, "sessionName") if err != nil { log.Println("error fetching session:", err) return &appError{err, "Error fetching session", 500} } token := session.Values["accessToken"] // Only fetch a list of people for connected users if token == nil { m := "Current user not connected" return &appError{errors.New(m), m, 401} } // Create a new authorized API client tok := new(oauth2.Token) tok.AccessToken = token.(string) client := oauth2.NewClient(oauth2.NoContext, oauth2.StaticTokenSource(tok)) service, err := plus.New(client) if err != nil { return &appError{err, "Create Plus Client", 500} } // Get a list of people that this user has shared with this app people := service.People.List("me", "visible") peopleFeed, err := people.Do() if err != nil { m := "Failed to refresh access token" if err.Error() == "AccessTokenRefreshError" { return &appError{errors.New(m), m, 500} } return &appError{err, m, 500} } w.Header().Set("Content-type", "application/json") err = json.NewEncoder(w).Encode(&peopleFeed) if err != nil { return &appError{err, "Convert PeopleFeed to JSON", 500} } return nil }
func TestSessionStore(t *testing.T) { // setup oauthmw sess := newSession() prov := newProvider() prov.Path = "/" prov.Configs = map[string]*oauth2.Config{ "google": newGoogleEndpoint(""), } prov.checkDefaults() // setup mux and middleware m0 := goji.NewMux() m0.UseC(sess.Handler) m0.UseC(prov.Login(nil)) m0.HandleFuncC(pat.Get("/ok"), okHandler) // do initial request to establish session r0, _ := get(m0, "/ok", nil, t) checkOK(r0, t) cookie := getCookie(r0, t) // set session store to bad data obj0 := swapSessionStore(sess.Store, &prov, "baddata", true, t) _, ok := obj0.(Store) if !ok { t.Error("item in session should be store") } // send another request r1, _ := get(m0, "/ok", cookie, t) checkOK(r1, t) // check that store is no longer corrupted obj1 := swapSessionStore(sess.Store, &prov, obj0, true, t) _, ok = obj1.(Store) if !ok { t.Error("store should have been fixed") } // test nil token _ = swapSessionStore(sess.Store, &prov, Store{Token: nil}, false, t) r2, _ := get(m0, "/ok", cookie, t) checkOK(r2, t) // setup mux and middleware m1 := goji.NewMux() m1.UseC(sess.Handler) m1.UseC(prov.RequireLogin(nil)) m1.HandleFuncC(pat.Get("/ok"), okHandler) // check expired token r3, _ := get(m1, "/ok", cookie, t) check(302, r3, t) // create token t3 := oauth2.Token{ AccessToken: "access", TokenType: "bearer", Expiry: time.Now().Add(1 * time.Hour), } // put token in session swapSessionStore(sess.Store, &prov, Store{ Token: &t3, States: make(map[string]StoreState), }, true, t) // check access r4, _ := get(m1, "/ok", cookie, t) checkOK(r4, t) // force token expiration t3.Expiry = time.Now().Add(-1 * time.Hour) // check that access has been revoked r5, _ := get(m1, "/ok", cookie, t) check(302, r5, t) }
func (s *sinaAuthSupply) GetProfileInfoURL(token *oauth2.Token) string { return "https://api.weibo.com/2/users/show.json" + "?" + "access_token=" + token.AccessToken + "&" + "uid=" + token.Extra("uid").(string) }