Beispiel #1
0
// 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
}
Beispiel #2
0
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
}
Beispiel #3
0
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
}
Beispiel #4
0
// 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
}
Beispiel #5
0
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())
}
Beispiel #6
0
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()
}
Beispiel #7
0
// 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)
}
Beispiel #8
0
// 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
}
Beispiel #9
0
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
}
Beispiel #10
0
// 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
}
Beispiel #11
0
// 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
}
Beispiel #12
0
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
}
Beispiel #13
0
// 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
}
Beispiel #14
0
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)
}
Beispiel #15
0
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)
}