examples/server/go/oauth.go
package main
import (
"encoding/json"
"errors"
"io"
"io/ioutil"
"log"
"net/http"
"strings"
"github.com/mrjones/oauth"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
func LoginWithTwitter(w http.ResponseWriter, r *http.Request) {
c := oauth.NewConsumer(
config.TWITTER_KEY,
config.TWITTER_SECRET,
oauth.ServiceProvider{
RequestTokenUrl: "https://api.twitter.com/oauth/request_token",
AuthorizeTokenUrl: "https://api.twitter.com/oauth/authenticate",
AccessTokenUrl: "https://api.twitter.com/oauth/access_token",
})
profileUrl := "https://api.twitter.com/1.1/users/show.json"
decoder := json.NewDecoder(r.Body)
var requestPayload struct {
OAuthToken string `json:"oauth_token"`
OAuthVerifier string `json:"oauth_verifier"`
}
err := decoder.Decode(&requestPayload)
if err != nil && err != io.EOF {
log.Println(err)
return
}
// Part 1/2: Initial request from Satellizer.
if requestPayload.OAuthToken == "" || requestPayload.OAuthVerifier == "" {
// Step 1. Obtain request token for the authorization popup.
requestToken, _, err := c.GetRequestTokenAndUrl(config.TWITTER_CALLBACK)
if err != nil {
log.Println(err)
return
}
// Step 2. Redirect to the authorization screen.
ServeJSON(w, r, &Response{
"oauth_token": requestToken.Token,
"oauth_token_secret": requestToken.Secret,
"oauth_callback_confirmed": "true",
}, 200)
} else {
// Part 2/2: Second request after Authorize app is clicked.
requestToken := &oauth.RequestToken{requestPayload.OAuthToken, config.TWITTER_SECRET}
// Step 3. Exchange oauth token and oauth verifier for access token.
accessToken, err := c.AuthorizeToken(requestToken, requestPayload.OAuthVerifier)
if err != nil {
log.Println(err)
return
}
// Step 4. Retrieve profile information about the current user.
response, err := c.Get(
profileUrl,
map[string]string{"screen_name": accessToken.AdditionalData["screen_name"]},
accessToken)
if err != nil {
log.Fatal(err)
}
defer response.Body.Close()
bits, err := ioutil.ReadAll(response.Body)
var profileData map[string]interface{}
err = json.Unmarshal(bits, &profileData)
db := GetDB(w, r)
if IsTokenSet(r) {
// Step 5a. Link user accounts.
existingUser, errM := FindUserByProvider(db, "twitter", accessToken.AdditionalData["user_id"])
if existingUser != nil {
ServeJSON(w, r, &Response{
"message": "There is already a Twitter account that belongs to you",
}, 409)
return
}
if errM != nil && errM.Reason != mgo.ErrNotFound {
HandleModelError(w, r, errM)
return
}
tokenData := GetToken(w, r)
user, errM := FindUserById(db, bson.ObjectIdHex(tokenData.ID))
if user == nil {
ServeJSON(w, r, &Response{
"message": "User not found",
}, 400)
return
}
if errM != nil && errM.Reason != mgo.ErrNotFound {
HandleModelError(w, r, errM)
return
}
user.Twitter = accessToken.AdditionalData["user_id"]
if user.DisplayName == "" {
user.DisplayName = accessToken.AdditionalData["screen_name"]
}
if user.Picture == "" {
user.Picture = strings.Replace(profileData["profile_image_url"].(string), "_normal", "", 1)
}
err = user.Save(db)
if err != nil {
ISR(w, r, errors.New("Couldn't save user profile informations"))
}
SetToken(w, r, user)
} else {
// Step 5b. Create a new user account or return an existing one.
existingUser, errM := FindUserByProvider(db, "twitter", accessToken.AdditionalData["user_id"])
if existingUser != nil {
SetToken(w, r, existingUser)
return
}
if errM != nil && errM.Reason != mgo.ErrNotFound {
HandleModelError(w, r, errM)
return
}
user := NewUser()
user.Email = accessToken.AdditionalData["user_id"] + "-satellizer@twitter.com"
user.Twitter = accessToken.AdditionalData["user_id"]
user.DisplayName = accessToken.AdditionalData["screen_name"]
user.Picture = strings.Replace(profileData["profile_image_url"].(string), "_normal", "", 1)
err = user.Save(db)
if err != nil {
ISR(w, r, err)
return
}
SetToken(w, r, user)
}
}
}