func LinkBitbucket(w http.ResponseWriter, r *http.Request, u *User) error { // get settings from database settings := database.SettingsMust() // bitbucket oauth1 consumer var consumer = oauth1.Consumer{ RequestTokenURL: "https://bitbucket.org/api/1.0/oauth/request_token/", AuthorizationURL: "https://bitbucket.org/!api/1.0/oauth/authenticate", AccessTokenURL: "https://bitbucket.org/api/1.0/oauth/access_token/", CallbackURL: settings.URL().String() + "/auth/login/bitbucket", ConsumerKey: settings.BitbucketKey, ConsumerSecret: settings.BitbucketSecret, } // get the oauth verifier verifier := r.FormValue("oauth_verifier") if len(verifier) == 0 { // Generate a Request Token requestToken, err := consumer.RequestToken() if err != nil { return err } // add the request token as a signed cookie SetCookie(w, r, "bitbucket_token", requestToken.Encode()) url, _ := consumer.AuthorizeRedirect(requestToken) http.Redirect(w, r, url, http.StatusSeeOther) return nil } // remove bitbucket token data once before redirecting // back to the application. defer DelCookie(w, r, "bitbucket_token") // get the tokens from the request requestTokenStr := GetCookie(r, "bitbucket_token") requestToken, err := oauth1.ParseRequestTokenStr(requestTokenStr) if err != nil { return err } // exchange for an access token accessToken, err := consumer.AuthorizeToken(requestToken, verifier) if err != nil { return err } // create the Bitbucket client client := bitbucket.New( settings.BitbucketKey, settings.BitbucketSecret, accessToken.Token(), accessToken.Secret(), ) // get the currently authenticated Bitbucket User user, err := client.Users.Current() if err != nil { return err } // update the user account u.BitbucketLogin = user.User.Username u.BitbucketToken = accessToken.Token() u.BitbucketSecret = accessToken.Secret() if err := database.SaveUser(u); err != nil { return err } http.Redirect(w, r, "/new/bitbucket.org", http.StatusSeeOther) return nil }
// Authorize handles Bitbucket API Authorization func (r *Bitbucket) Authorize(res http.ResponseWriter, req *http.Request) (*model.Login, error) { consumer := oauth1.Consumer{ RequestTokenURL: "https://bitbucket.org/api/1.0/oauth/request_token/", AuthorizationURL: "https://bitbucket.org/!api/1.0/oauth/authenticate", AccessTokenURL: "https://bitbucket.org/api/1.0/oauth/access_token/", CallbackURL: httputil.GetScheme(req) + "://" + httputil.GetHost(req) + "/api/auth/bitbucket.org", ConsumerKey: r.Client, ConsumerSecret: r.Secret, } // get the oauth verifier verifier := req.FormValue("oauth_verifier") if len(verifier) == 0 { // Generate a Request Token requestToken, err := consumer.RequestToken() if err != nil { return nil, err } // add the request token as a signed cookie httputil.SetCookie(res, req, "bitbucket_token", requestToken.Encode()) url, _ := consumer.AuthorizeRedirect(requestToken) http.Redirect(res, req, url, http.StatusSeeOther) return nil, nil } // remove bitbucket token data once before redirecting // back to the application. defer httputil.DelCookie(res, req, "bitbucket_token") // get the tokens from the request requestTokenStr := httputil.GetCookie(req, "bitbucket_token") requestToken, err := oauth1.ParseRequestTokenStr(requestTokenStr) if err != nil { return nil, err } // exchange for an access token accessToken, err := consumer.AuthorizeToken(requestToken, verifier) if err != nil { return nil, err } // create the Bitbucket client client := bitbucket.New( r.Client, r.Secret, accessToken.Token(), accessToken.Secret(), ) // get the currently authenticated Bitbucket User user, err := client.Users.Current() if err != nil { return nil, err } // put the user data in the common format login := model.Login{ Login: user.User.Username, Access: accessToken.Token(), Secret: accessToken.Secret(), Name: user.User.DisplayName, } email, _ := client.Emails.FindPrimary(user.User.Username) if email != nil { login.Email = email.Email } return &login, nil }
func (c *Client) do(method string, path string, params url.Values, values url.Values, v interface{}) error { // if this is the guest client then we don't need // to sign the request ... we will execute just // a simple http request. if c == Guest { return c.guest(method, path, params, values, v) } // create the client var client = oauth1.Consumer{ ConsumerKey: c.ConsumerKey, ConsumerSecret: c.ConsumerSecret, } // create the URI uri, err := url.Parse("https://api.bitbucket.org/1.0" + path) if err != nil { return err } if params != nil && len(params) > 0 { uri.RawQuery = params.Encode() } // create the access token token := oauth1.NewAccessToken(c.AccessToken, c.TokenSecret, nil) // create the request req := &http.Request{ URL: uri, Method: method, ProtoMajor: 1, ProtoMinor: 1, Close: true, } if values != nil && len(values) > 0 { body := []byte(values.Encode()) buf := bytes.NewBuffer(body) req.Body = ioutil.NopCloser(buf) } // add the Form data to the request // (we'll need this in order to sign the request) req.Form = values // sign the request if err := client.Sign(req, token); err != nil { return err } // make the request using the default http client resp, err := DefaultClient.Do(req) if err != nil { return err } // Read the bytes from the body (make sure we defer close the body) defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return err } // Check for an http error status (ie not 200 StatusOK) switch resp.StatusCode { case 404: return ErrNotFound case 403: return ErrForbidden case 401: return ErrNotAuthorized case 400: return ErrBadRequest } // Unmarshall the JSON response if v != nil { return json.Unmarshal(body, v) } return nil }